From 72dfb9c7e3e49d22c94c50126aa0e974aa69663c Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 9 Sep 2021 09:29:27 -0500 Subject: [PATCH 01/32] skip flaky suite, #109564 --- .../functional/apps/graph/feature_controls/graph_security.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts index cc121dccfb13e..913a5034bacc5 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts @@ -16,7 +16,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const appsMenu = getService('appsMenu'); const globalNav = getService('globalNav'); - describe('security', () => { + // FLAKY https://github.com/elastic/kibana/issues/109564 + describe.skip('security', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); // ensure we're logged out so we can login as the appropriate users From a045c8ab4a653f89db700e52c2f52f6b9e765da0 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Thu, 9 Sep 2021 09:50:14 -0500 Subject: [PATCH 02/32] Fix bug where flyout state was not reset (#111662) This PR fixes a bug in both App Search and Workplace Search where the role mappings flyout state was not being cleared when updating a role mapping. The issue is that the state of the flyout is determined by the existence of a role mapping and this was not being cleared when the role mapping was saved. --- .../role_mappings/role_mappings_logic.test.ts | 10 ++++++++++ .../components/role_mappings/role_mappings_logic.ts | 1 + .../views/role_mappings/role_mappings_logic.test.ts | 10 ++++++++++ .../views/role_mappings/role_mappings_logic.ts | 1 + 4 files changed, 22 insertions(+) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.test.ts index e63469f985d7d..14d97c7dd3f4d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.test.ts @@ -418,6 +418,16 @@ describe('RoleMappingsLogic', () => { expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); + + it('resets roleMapping state', () => { + mount({ + ...mappingsServerProps, + roleMapping: asRoleMapping, + }); + RoleMappingsLogic.actions.initializeRoleMappings(); + + expect(RoleMappingsLogic.values.roleMapping).toEqual(null); + }); }); describe('initializeRoleMapping', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.ts index 6dac9e481f7ef..7b7bcd864ebd0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/role_mappings/role_mappings_logic.ts @@ -178,6 +178,7 @@ export const RoleMappingsLogic = kea roleMapping, + initializeRoleMappings: () => null, resetState: () => null, closeUsersAndRolesFlyout: () => null, }, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.test.ts index 1cf1adfd00200..3f5a63275f05d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.test.ts @@ -376,6 +376,16 @@ describe('RoleMappingsLogic', () => { expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); + + it('resets roleMapping state', () => { + mount({ + ...mappingsServerProps, + roleMapping: wsRoleMapping, + }); + RoleMappingsLogic.actions.initializeRoleMappings(); + + expect(RoleMappingsLogic.values.roleMapping).toEqual(null); + }); }); describe('initializeRoleMapping', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts index 64cec51001647..55f82a07bf405 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/role_mappings/role_mappings_logic.ts @@ -168,6 +168,7 @@ export const RoleMappingsLogic = kea roleMapping, + initializeRoleMappings: () => null, resetState: () => null, closeUsersAndRolesFlyout: () => null, }, From 86d61a4f6c961822d76a22a0945901c1c9e9cc80 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Thu, 9 Sep 2021 09:51:32 -0500 Subject: [PATCH 03/32] Fix a bug where users not populated (#111660) In https://github.com/elastic/kibana/pull/109008, we fixed an issue where Role mappings were not populated on changes (adding/deleting). However, we did not apply the same fix for Users in the table under Role mappings. This PR does that. --- .../applications/shared/role_mapping/users_table.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_table.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_table.tsx index 3b6e2dc440a76..3dc5560a9eaba 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/users_table.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { EuiBadge, EuiBasicTableColumn, EuiInMemoryTable, EuiTextColor } from '@elastic/eui'; import type { EuiSearchBarOnChangeArgs } from '@elastic/eui'; @@ -57,6 +57,8 @@ const noItemsPlaceholder = ; const invitationBadge = {INVITATION_PENDING_LABEL}; const deactivatedBadge = {DEACTIVATED_LABEL}; +type Users = Array>; + export const UsersTable: React.FC = ({ accessItemKey, singleUserRoleMappings, @@ -72,9 +74,13 @@ export const UsersTable: React.FC = ({ id: user.roleMapping.id, accessItems: (user.roleMapping as SharedRoleMapping)[accessItemKey], invitation: user.invitation, - })) as unknown) as Array>; + })) as unknown) as Users; + + const [items, setItems] = useState([] as Users); - const [items, setItems] = useState(users); + useEffect(() => { + setItems(users); + }, [singleUserRoleMappings]); const columns: Array> = [ { From 13f948d6d10498e1c5f9c784611e1c23744f02cd Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 9 Sep 2021 10:11:23 -0500 Subject: [PATCH 04/32] Remove unused dependencies (#109279) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 15 ----- yarn.lock | 165 +++------------------------------------------------ 2 files changed, 7 insertions(+), 173 deletions(-) diff --git a/package.json b/package.json index e3f65f7c50853..e8ac3a65924b2 100644 --- a/package.json +++ b/package.json @@ -184,12 +184,9 @@ "JSONStream": "1.3.5", "abort-controller": "^3.0.0", "abortcontroller-polyfill": "^1.4.0", - "ajv": "^6.12.4", "angular": "^1.8.0", "angular-aria": "^1.8.0", - "angular-elastic": "^2.5.1", "angular-recursion": "^1.0.5", - "angular-resource": "1.8.0", "angular-route": "^1.8.0", "angular-sanitize": "^1.8.0", "angular-sortable-view": "^0.0.17", @@ -201,7 +198,6 @@ "brace": "0.11.1", "broadcast-channel": "^3.0.3", "chalk": "^4.1.0", - "check-disk-space": "^2.1.0", "cheerio": "^1.0.0-rc.9", "chokidar": "^3.4.3", "chroma-js": "^1.4.1", @@ -237,15 +233,12 @@ "fflate": "^0.6.9", "file-saver": "^1.3.8", "file-type": "^10.9.0", - "focus-trap-react": "^3.1.1", "font-awesome": "4.7.0", - "formsy-react": "^1.1.5", "fp-ts": "^2.3.1", "geojson-vt": "^3.2.1", "get-port": "^5.0.0", "getopts": "^2.2.5", "getos": "^3.1.0", - "github-markdown-css": "^2.10.0", "glob": "^7.1.2", "glob-all": "^3.2.1", "globby": "^11.0.3", @@ -323,9 +316,7 @@ "pngjs": "^3.4.0", "polished": "^3.7.2", "prop-types": "^15.7.2", - "proper-lockfile": "^3.2.0", "proxy-from-env": "1.0.0", - "proxyquire": "1.8.0", "puid": "1.0.7", "puppeteer": "^8.0.0", "query-string": "^6.13.2", @@ -341,7 +332,6 @@ "react-dropzone": "^4.2.9", "react-fast-compare": "^2.0.4", "react-grid-layout": "^0.16.2", - "react-input-range": "^1.3.0", "react-intl": "^2.8.0", "react-is": "^16.8.0", "react-markdown": "^4.3.1", @@ -406,9 +396,7 @@ "type-detect": "^4.0.8", "typescript-fsa": "^3.0.0", "typescript-fsa-reducers": "^1.2.2", - "ui-select": "0.19.8", "unified": "^9.2.1", - "unstated": "^2.1.1", "use-resize-observer": "^6.0.0", "utility-types": "^3.10.0", "uuid": "3.3.2", @@ -601,7 +589,6 @@ "@types/prettier": "^2.1.5", "@types/pretty-ms": "^5.0.0", "@types/prop-types": "^15.7.3", - "@types/proper-lockfile": "^3.0.1", "@types/rbush": "^3.0.0", "@types/reach__router": "^1.2.6", "@types/react": "^16.9.36", @@ -696,7 +683,6 @@ "cypress-promise": "^1.1.0", "cypress-real-events": "^1.4.0", "debug": "^2.6.9", - "del-cli": "^3.0.1", "delete-empty": "^2.0.0", "dependency-check": "^4.1.0", "diff": "^4.0.1", @@ -830,7 +816,6 @@ "tape": "^5.0.1", "tar-fs": "^2.1.0", "tempy": "^0.3.0", - "terminal-link": "^2.1.1", "terser": "^5.7.1", "terser-webpack-plugin": "^2.1.2", "tough-cookie": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index bdf256424c5eb..1c91896c1f063 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5827,11 +5827,6 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== -"@types/proper-lockfile@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/proper-lockfile/-/proper-lockfile-3.0.1.tgz#dd770a2abce3adbcce3bd1ed892ce2f5f17fbc86" - integrity sha512-ODOjqxmaNs0Zkij+BJovsNJRSX7BJrr681o8ZnNTNIcTermvVFzLpz/XFtfg3vNrlPVTJY1l4e9h2LvHoxC1lg== - "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" @@ -6975,13 +6970,6 @@ angular-aria@^1.8.0: resolved "https://registry.yarnpkg.com/angular-aria/-/angular-aria-1.8.0.tgz#97aec9b1e8bafd07d5fab30f98d8ec832e18e25d" integrity sha512-eCQI6EwgY6bYHdzIUfDABHnZjoZ3bNYpCsnceQF4bLfbq1QtZ7raRPNca45sj6C9Pfjde6PNcEDvuLozFPYnrQ== -angular-elastic@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/angular-elastic/-/angular-elastic-2.5.1.tgz#e938ab1bd8c76415b8ca6514b15fe3593a5df535" - integrity sha1-6TirG9jHZBW4ymUUsV/jWTpd9TU= - dependencies: - angular ">=1.0.6" - angular-mocks@^1.7.9: version "1.7.9" resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.7.9.tgz#0a3b7e28b9a493b4e3010ed2b0f69a68e9b4f79b" @@ -6992,11 +6980,6 @@ angular-recursion@^1.0.5: resolved "https://registry.yarnpkg.com/angular-recursion/-/angular-recursion-1.0.5.tgz#cd405428a0bf55faf52eaa7988c1fe69cd930543" integrity sha1-zUBUKKC/Vfr1Lqp5iMH+ac2TBUM= -angular-resource@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/angular-resource/-/angular-resource-1.8.0.tgz#578ef122e7cb7bcc6c0ad6c2451dc3d27fd570ba" - integrity sha512-9woUq3kDwoT7R6SjKX8vaJMhOplYBm9sqRAxKgDhDIdPyA8iBowqQIusf9+8Q+z/HlXb8ZXvKspJyKXrxmKdvg== - angular-route@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.8.0.tgz#cb8066c5d34284ffd6a15ac7be1b3d51c5ad7bb2" @@ -7012,7 +6995,7 @@ angular-sortable-view@^0.0.17: resolved "https://registry.yarnpkg.com/angular-sortable-view/-/angular-sortable-view-0.0.17.tgz#99e2679951a86b6ee6ff27b099022943c683fb4f" integrity sha512-2WkhM0Lt/wyMyrX/+7ve9ejSegBd7A4eRBNHEIJz8XMBIOjt+3oM1WpcAm+qNThkmNmmQaDeaYv0TQZw/WDMBw== -angular@>=1.0.6, angular@^1.8.0: +angular@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.0.tgz#b1ec179887869215cab6dfd0df2e42caa65b1b51" integrity sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg== @@ -7724,11 +7707,6 @@ attr-accept@^2.0.0: resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.1.tgz#89b48de019ed4342f1865626b4389c666b3ed231" integrity sha512-GpefLMsbH5ojNgfTW+OBin2xKzuHfyeNA+qCktzZojBhbA/lPZdCFMWdwk5ajb989Ok7ZT+EADqvW3TAFNMjhA== -autobind-decorator@^1.3.4: - version "1.4.3" - resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-1.4.3.tgz#4c96ffa77b10622ede24f110f5dbbf56691417d1" - integrity sha1-TJb/p3sQYi7eJPEQ9du/VmkUF9E= - autoprefixer@^9.7.2, autoprefixer@^9.7.4: version "9.8.5" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.5.tgz#2c225de229ddafe1d1424c02791d0c3e10ccccaa" @@ -9395,11 +9373,6 @@ charenc@~0.0.1: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -check-disk-space@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/check-disk-space/-/check-disk-space-2.1.0.tgz#2e77fe62f30d9676dc37a524ea2008f40c780295" - integrity sha512-f0nx9oJF/AVF8nhSYlF1EBvMNnO+CXyLwKhPvN1943iOMI9TWhQigLZm80jAf0wzQhwKkzA8XXjyvuVUeGGcVQ== - check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -10469,11 +10442,6 @@ create-react-context@0.3.0, create-react-context@^0.3.0: gud "^1.0.0" warning "^4.0.3" -create-react-context@^0.1.5: - version "0.1.6" - resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.1.6.tgz#0f425931d907741127acc6e31acb4f9015dd9fdc" - integrity sha512-eCnYYEUEc5i32LHwpE/W7NlddOB9oHwsPaWtWzYtflNkkwa3IfindIcoXdVWs12zCbwaMCavKNu84EXogVIWHw== - cronstrue@^1.51.0: version "1.51.0" resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-1.51.0.tgz#7a63153d61d940344049037628da38a60784c8e2" @@ -11653,14 +11621,6 @@ defined@^1.0.0, defined@~1.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= -del-cli@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/del-cli/-/del-cli-3.0.1.tgz#2d27ff260204b5104cadeda86f78f180a4ebe89a" - integrity sha512-BLHItGr82rUbHhjMu41d+vw9Md49i81jmZSV00HdTq4t+RTHywmEht/23mNFpUl2YeLYJZJyGz4rdlMAyOxNeg== - dependencies: - del "^5.1.0" - meow "^6.1.1" - del@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" @@ -13831,14 +13791,6 @@ filesize@6.1.0: resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" integrity sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg== -fill-keys@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" - integrity sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA= - dependencies: - is-object "~1.0.1" - merge-descriptors "~1.0.0" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -14044,20 +13996,6 @@ focus-lock@^0.7.0: resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.7.0.tgz#b2bfb0ca7beacc8710a1ff74275fe0dc60a1d88a" integrity sha512-LI7v2mH02R55SekHYdv9pRHR9RajVNyIJ2N5IEkWbg7FT5ZmJ9Hw4mWxHeEUcd+dJo0QmzztHvDvWcc7prVFsw== -focus-trap-react@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-3.1.2.tgz#4dd021ccd028bbd3321147d132cdf7585d6d1394" - integrity sha512-MoQmONoy9gRPyrC5DGezkcOMGgx7MtIOAQDHe098UtL2sA2vmucJwEmQisb+8LRXNYFHxuw5zJ1oLFeKu4Mteg== - dependencies: - focus-trap "^2.0.1" - -focus-trap@^2.0.1: - version "2.4.5" - resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-2.4.5.tgz#91c9c9ffb907f8f4446d80202dda9c12c2853ddb" - integrity sha512-jkz7Dh6Pb4ox+z24GhVABDE7lFT19z7KVrpYGH5qqI6KK3Y2IcXhBx844W6ZXYahD+jOEUcGz49dLakXg2sjOQ== - dependencies: - tabbable "^1.0.3" - folktale@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/folktale/-/folktale-2.0.1.tgz#6dc26a65565aefdef9520223e022dddf5b8d8462" @@ -14155,11 +14093,6 @@ fork-ts-checker-webpack-plugin@4.1.6, fork-ts-checker-webpack-plugin@^4.1.4: tapable "^1.0.0" worker-rpc "^0.1.0" -form-data-to-object@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/form-data-to-object/-/form-data-to-object-0.2.0.tgz#f7a8e68ddd910a1100a65e25ac6a484143ff8168" - integrity sha1-96jmjd2RChEApl4lrGpIQUP/gWg= - form-data@^2.3.1, form-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.0.tgz#094ec359dc4b55e7d62e0db4acd76e89fe874d37" @@ -14211,14 +14144,6 @@ formidable@^1.2.0: resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== -formsy-react@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/formsy-react/-/formsy-react-1.1.5.tgz#ee0911bb70712eb6fb9924d56fdb974a19006955" - integrity sha512-nNWe4Vbp6aDQ/zSxJ7gVQgD5+avFRVbydcjA2Om42flxpQFrKE54AAbuyEj3Jvv+2b9LVl+WLMAPalyvLjwNcQ== - dependencies: - form-data-to-object "^0.2.0" - prop-types "^15.5.10" - forwarded-parse@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/forwarded-parse/-/forwarded-parse-2.1.0.tgz#1ae9d7a4be3af884f74d936d856f7d8c6abd0439" @@ -14589,11 +14514,6 @@ gifwrap@^0.9.2: image-q "^1.1.1" omggif "^1.0.10" -github-markdown-css@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/github-markdown-css/-/github-markdown-css-2.10.0.tgz#0612fed22816b33b282f37ef8def7a4ecabfe993" - integrity sha512-RX5VUC54uX6Lvrm226M9kMzsNeOa81MnKyxb3J0G5KLjyoOySOZgwyKFkUpv6iUhooiUZdogk+OTwQPJ4WttYg== - github-slugger@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.3.0.tgz#9bd0a95c5efdfc46005e82a906ef8e2a059124c9" @@ -16675,7 +16595,7 @@ is-obj@^2.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== -is-object@^1.0.1, is-object@~1.0.1: +is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= @@ -17696,7 +17616,7 @@ jju@~1.4.0: resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= -joi@*, joi@^17.4.0: +joi@*, joi@^17.3.0, joi@^17.4.0: version "17.4.0" resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.0.tgz#b5c2277c8519e016316e49ababd41a1908d9ef20" integrity sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg== @@ -17707,17 +17627,6 @@ joi@*, joi@^17.4.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" -joi@^17.3.0: - version "17.3.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.3.0.tgz#f1be4a6ce29bc1716665819ac361dfa139fff5d2" - integrity sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg== - dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.0" - "@sideway/formula" "^3.0.0" - "@sideway/pinpoint" "^2.0.0" - jpeg-js@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.0.4.tgz#06aaf47efec7af0b1924a59cd695a6d2b5ed870e" @@ -19321,23 +19230,6 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" -meow@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.1.tgz#1ad64c4b76b2a24dfb2f635fddcadf320d251467" - integrity sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg== - dependencies: - "@types/minimist" "^1.2.0" - camelcase-keys "^6.2.2" - decamelize-keys "^1.1.0" - hard-rejection "^2.1.0" - minimist-options "^4.0.2" - normalize-package-data "^2.5.0" - read-pkg-up "^7.0.1" - redent "^3.0.0" - trim-newlines "^3.0.0" - type-fest "^0.13.1" - yargs-parser "^18.1.3" - meow@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/meow/-/meow-7.0.1.tgz#1ed4a0a50b3844b451369c48362eb0515f04c1dc" @@ -19392,7 +19284,7 @@ meow@^9.0.0: type-fest "^0.18.0" yargs-parser "^20.2.3" -merge-descriptors@1.0.1, merge-descriptors@~1.0.0: +merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= @@ -19850,11 +19742,6 @@ module-details-from-path@^1.0.3: resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" integrity sha1-EUyUlnPiqKNenTV4hSeqN7Z52is= -module-not-found-error@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0" - integrity sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA= - moment-duration-format@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/moment-duration-format/-/moment-duration-format-2.3.2.tgz#5fa2b19b941b8d277122ff3f87a12895ec0d6212" @@ -22471,15 +22358,6 @@ propagate@^2.0.0: resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== -proper-lockfile@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-3.2.0.tgz#89ca420eea1d55d38ca552578851460067bcda66" - integrity sha512-iMghHHXv2bsxl6NchhEaFck8tvX3F9cknEEh1SUpguUOBjN7PAAW9BLzmbc1g/mCD1gY3EE2EABBHPJfFdHFmA== - dependencies: - graceful-fs "^4.1.11" - retry "^0.12.0" - signal-exit "^3.0.2" - property-information@^5.0.0, property-information@^5.0.1, property-information@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.5.0.tgz#4dc075d493061a82e2b7d096f406e076ed859943" @@ -22534,15 +22412,6 @@ proxy-from-env@^1.0.0, proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -proxyquire@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-1.8.0.tgz#02d514a5bed986f04cbb2093af16741535f79edc" - integrity sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw= - dependencies: - fill-keys "^1.0.2" - module-not-found-error "^1.0.0" - resolve "~1.1.7" - prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -23141,14 +23010,6 @@ react-input-autosize@^2.2.1, react-input-autosize@^2.2.2: dependencies: prop-types "^15.5.8" -react-input-range@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/react-input-range/-/react-input-range-1.3.0.tgz#f96d001631ab817417f1e26d8f9f9684b4827f59" - integrity sha1-+W0AFjGrgXQX8eJtj5+WhLSCf1k= - dependencies: - autobind-decorator "^1.3.4" - prop-types "^15.5.8" - react-inspector@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-5.0.1.tgz#8a30f3d488c4f40203624bbe24800f508ae05d3a" @@ -24518,7 +24379,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.1.7, resolve@~1.1.7: +resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= @@ -26601,7 +26462,7 @@ syntax-error@^1.1.1: dependencies: acorn-node "^1.2.0" -tabbable@1.1.3, tabbable@^1.0.3: +tabbable@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.3.tgz#0e4ee376f3631e42d7977a074dbd2b3827843081" integrity sha512-nOWwx35/JuDI4ONuF0ZTo6lYvI0fY0tZCH1ErzY2EXfu4az50ZyiUX8X073FLiZtmWUVlkRnuXsehjJgCw9tYg== @@ -26841,7 +26702,7 @@ term-size@^2.1.0: resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== -terminal-link@^2.0.0, terminal-link@^2.1.1: +terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== @@ -27640,11 +27501,6 @@ uglify-to-browserify@~1.0.0: resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= -ui-select@0.19.8: - version "0.19.8" - resolved "https://registry.yarnpkg.com/ui-select/-/ui-select-0.19.8.tgz#74860848a7fd8bc494d9856d2f62776ea98637c1" - integrity sha1-dIYISKf9i8SU2YVtL2J3bqmGN8E= - uid-safe@2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" @@ -28068,13 +27924,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -unstated@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/unstated/-/unstated-2.1.1.tgz#36b124dfb2e7a12d39d0bb9c46dfb6e51276e3a2" - integrity sha512-fORlTWMZxq7NuMJDxyIrrYIZKN7wEWYQ9SiaJfIRcSpsowr6Ph/JIfK2tgtXLW614JfPG/t5q9eEIhXRCf55xg== - dependencies: - create-react-context "^0.1.5" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" From c6c4f52fc373e5702eb9452a0d3879bdf06caa2a Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Thu, 9 Sep 2021 17:15:44 +0200 Subject: [PATCH 05/32] [Lens] comment redux logger (#111513) * [Lens] comment redux logger * Update x-pack/plugins/lens/public/state_management/index.ts Co-authored-by: Marco Liberati * Update x-pack/plugins/lens/public/state_management/index.ts Co-authored-by: Marco Liberati Co-authored-by: Marco Liberati Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/lens/public/state_management/index.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/lens/public/state_management/index.ts b/x-pack/plugins/lens/public/state_management/index.ts index a23a040de2361..1d8f4fdffa730 100644 --- a/x-pack/plugins/lens/public/state_management/index.ts +++ b/x-pack/plugins/lens/public/state_management/index.ts @@ -6,7 +6,7 @@ */ import { configureStore, getDefaultMiddleware, DeepPartial } from '@reduxjs/toolkit'; -import logger from 'redux-logger'; +import { createLogger } from 'redux-logger'; import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'; import { lensSlice } from './lens_slice'; import { timeRangeMiddleware } from './time_range_middleware'; @@ -50,7 +50,14 @@ export const makeConfigureStore = ( optimizingMiddleware(), timeRangeMiddleware(storeDeps.lensServices.data), ]; - if (process.env.NODE_ENV === 'development') middleware.push(logger); + if (process.env.NODE_ENV === 'development') { + middleware.push( + createLogger({ + // @ts-ignore + predicate: () => window.ELASTIC_LENS_LOGGER, + }) + ); + } return configureStore({ reducer, From fdc7aac4aa7c32f18d63475a4904968029796c64 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Thu, 9 Sep 2021 08:28:05 -0700 Subject: [PATCH 06/32] [DOCS] APM failed transaction correlations (#111219) --- docs/apm/correlations.asciidoc | 88 ++++++------------ .../correlations-failed-transactions.png | Bin 0 -> 151440 bytes docs/apm/images/error-rate-hover.png | Bin 524077 -> 0 bytes 3 files changed, 27 insertions(+), 61 deletions(-) create mode 100644 docs/apm/images/correlations-failed-transactions.png delete mode 100644 docs/apm/images/error-rate-hover.png diff --git a/docs/apm/correlations.asciidoc b/docs/apm/correlations.asciidoc index c0c18433c9021..2165994b8372f 100644 --- a/docs/apm/correlations.asciidoc +++ b/docs/apm/correlations.asciidoc @@ -58,68 +58,34 @@ out, you can begin viewing sample traces to continue your investigation. [[correlations-error-rate]] ==== Find failed transaction correlations -The correlations on the *Error rate* tab help you discover which fields are -contributing to failed transactions. - -By default, a number of attributes commonly known to cause performance issues, -like version, infrastructure, and location, are included, but all are completely -customizable to your APM data. Find something interesting? A quick click of a -button will auto-query your data as you work to resolve the underlying issue. - -The error rate over time chart visualizes the change in error rate over the selected time frame. -Correlated attributes are sorted by _Impact_–a visual representation of the -{ref}/search-aggregations-bucket-significantterms-aggregation.html[significant terms aggregation] -score that powers correlations. -Attributes with a high impact, or attributes present in a large percentage of failed transactions, -may contribute to increased error rates. - -To find error rate correlations, hover over each potentially correlated attribute to -compare the error rate distribution of transactions with and without the selected attribute. - -For example, in the screenshot below, the field `url.original` and value `http://localhost:3100...` -existed in 100% of failed transactions between 6:00 and 10:30. +beta::[] + +The correlations on the *Failed transaction correlations* tab help you discover +which attributes are most influential in distinguishing between transaction +failures and successes. In this context, the success or failure of a transaction +is determined by its {ecs-ref}/ecs-event.html#field-event-outcome[event.outcome] +value. For example, APM agents set the `event.outcome` to `failure` when an HTTP +transaction returns a `5xx` status code. + +// The chart highlights the failed transactions in the overall latency distribution for the transaction group. +If there are attributes that have a statistically significant correlation with +failed transactions, they are listed in a table. The table is sorted by scores, +which are mapped to high, medium, or low impact levels. Attributes with high +impact levels are more likely to contribute to failed transactions. +// By default, the attribute with the highest score is added to the chart. To see a different attribute in the chart, hover over its row in the table. + +For example, in the screenshot below, the field +`kubernetes.pod.name` and value `frontend-node-59dff47885-fl5lb` has a medium +impact level and existed in 19% of the failed transactions. [role="screenshot"] -image::apm/images/error-rate-hover.png[Correlations errors hover effect] - -Select the `+` filter to create a new query in the {apm-app} for transactions with -`url.original: http://localhost:3100...`. With the "noise" now filtered out, -you can begin viewing sample traces to continue your investigation. - -As you sift through erroneous transactions, you'll likely notice other interesting attributes. -Return to the correlations fly-out and select *Customize fields* to search on these new attributes. -You may need to do this a few times–each time filtering out more and more noise and bringing you -closer to a diagnosis. - -[discrete] -[[correlations-customize-fields]] -===== Customize fields - -By default, a handful of attributes commonly known to cause performance issues -are included in the analysis on the *Error rate* tab. You can add and remove -fields under the **Customize fields** dropdown. - -The following fields are selected by default. To keep the default list -manageable, only the first six matching fields with wildcards are used. - -**Frontend (RUM) agent:** - -* `labels.*` -* `user.*` -* `user_agent.name` -* `user_agent.os.name` -* `url.original` - -**Backend agents:** +image::apm/images/correlations-failed-transactions.png[Failed transaction correlations] -* `labels.*` -* `host.ip` -* `service.node.name` -* `service.version` +TIP: Some details, such as the failure and success percentages, are available +only when the +<> +advanced setting is enabled. -[TIP] -==== -* Want to start over? Select **reset** to clear your customizations. -* The *Latency* tab does not have a **Customize fields** dropdown, since it -automatically considers all relevant fields in the transactions. -==== +Select the `+` filter to create a new query in the {apm-app} for transactions +with this attribute. You might do his for multiple attributes--each time +filtering out more and more noise and bringing you closer to a diagnosis. \ No newline at end of file diff --git a/docs/apm/images/correlations-failed-transactions.png b/docs/apm/images/correlations-failed-transactions.png new file mode 100644 index 0000000000000000000000000000000000000000..3258b44f7097bc1c5df52d7633fcd9ab368d4e51 GIT binary patch literal 151440 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 z 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

NmS3A|&6jgDQ;2(|6ku9d4dr9(*>#$tb&u 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 HT88}()HBOG literal 0 HcmV?d00001 diff --git a/docs/apm/images/error-rate-hover.png b/docs/apm/images/error-rate-hover.png deleted file mode 100644 index 69f000930931897e233384f9530dc7f505f39ba1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 524077 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 WeIBg}6~+_bkD{!qO!2LILH`G$q*KZO From 930bc9c1e3d947a1c6683bf189147d1bfbe07ac8 Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Thu, 9 Sep 2021 11:55:57 -0400 Subject: [PATCH 07/32] Use correct z-index for timeline global footer (#111492) --- .../security_solution/public/app/home/template_wrapper/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx b/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx index 67d9943fabe83..99f67ba26e8f1 100644 --- a/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx @@ -42,7 +42,6 @@ const StyledKibanaPageTemplate = styled(KibanaPageTemplate)<{ transform: ${( { $isShowingTimelineOverlay } // Since the bottom bar wraps the whole overlay now, need to override any transforms when it is open ) => ($isShowingTimelineOverlay ? 'none' : 'translateY(calc(100% - 50px))')}; - z-index: ${({ theme }) => theme.eui.euiZLevel8}; .${IS_DRAGGING_CLASS_NAME} & { // When a drag is in process the bottom flyout should slide up to allow a drop From 7f441b49b3804271270f7f3f883b300306656b6e Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Thu, 9 Sep 2021 17:58:58 +0200 Subject: [PATCH 08/32] [ML] Functional tests - skip color assertions in cloud (#111695) This PR skips color assertions during functional tests in cloud environments. --- x-pack/test/functional/services/ml/common_ui.ts | 5 +++++ x-pack/test/functional/services/transform/wizard.ts | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/x-pack/test/functional/services/ml/common_ui.ts b/x-pack/test/functional/services/ml/common_ui.ts index 9af9aaa45be5c..65621c4959d37 100644 --- a/x-pack/test/functional/services/ml/common_ui.ts +++ b/x-pack/test/functional/services/ml/common_ui.ts @@ -241,6 +241,11 @@ export function MachineLearningCommonUIProvider({ channelTolerance = 10, valueTolerance = 10 ) { + if (process.env.TEST_CLOUD) { + log.warning('Not running color assertions in cloud'); + return; + } + await retry.tryForTime(30 * 1000, async () => { await testSubjects.existOrFail(dataTestSubj); diff --git a/x-pack/test/functional/services/transform/wizard.ts b/x-pack/test/functional/services/transform/wizard.ts index 607f2ee120ed1..feda634e90cf2 100644 --- a/x-pack/test/functional/services/transform/wizard.ts +++ b/x-pack/test/functional/services/transform/wizard.ts @@ -22,6 +22,7 @@ export type HistogramCharts = Array<{ export function TransformWizardProvider({ getService, getPageObjects }: FtrProviderContext) { const aceEditor = getService('aceEditor'); const canvasElement = getService('canvasElement'); + const log = getService('log'); const testSubjects = getService('testSubjects'); const comboBox = getService('comboBox'); const retry = getService('retry'); @@ -241,6 +242,11 @@ export function TransformWizardProvider({ getService, getPageObjects }: FtrProvi }, async assertIndexPreviewHistogramCharts(expectedHistogramCharts: HistogramCharts) { + if (process.env.TEST_CLOUD) { + log.warning('Not running color assertions in cloud'); + return; + } + // For each chart, get the content of each header cell and assert // the legend text and column id and if the chart should be present or not. await retry.tryForTime(5000, async () => { From a7c3172285a7852bcf73527f57993a97eb053cd2 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Thu, 9 Sep 2021 12:05:43 -0400 Subject: [PATCH 09/32] add doc about git clean for working around ts issues (#111572) * add doc about git clean for working around ts issues * Update dev_docs/troubleshooting.mdx Co-authored-by: Spencer * Update dev_docs/troubleshooting.mdx Co-authored-by: Spencer * Update troubleshooting.mdx Co-authored-by: Spencer --- dev_docs/troubleshooting.mdx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 dev_docs/troubleshooting.mdx diff --git a/dev_docs/troubleshooting.mdx b/dev_docs/troubleshooting.mdx new file mode 100644 index 0000000000000..f624a8cd77507 --- /dev/null +++ b/dev_docs/troubleshooting.mdx @@ -0,0 +1,28 @@ +--- +id: kibTroubleshooting +slug: /kibana-dev-docs/troubleshooting +title: Troubleshooting +summary: A collection of tips for working around strange issues. +date: 2021-09-08 +tags: ['kibana', 'onboarding', 'dev', 'troubleshooting'] +--- + +### Typescript issues + +When switching branches, sometimes the TypeScript cache can get mixed up and show some invalid errors. If you run into TypeScript issues (invalid errors, or if it's taking too long to build types), here a few things to try. + +1. Build TypeScript references with the clean command. + +``` +node scripts/build_ts_refs --clean +``` + +2. Restore your repository to a totally fresh state by running `git clean` + +``` +# dry-run the clean to see what will be deleted +git clean -fdxn -e /config -e /.vscode + +# review the files which will be deleted, consider adding some more excludes (-e) +# re-run without the dry-run (-n) flag to actually delete the files +``` From 7ae423c5bbc0d8cc8707b93a363da73d40c4d0d1 Mon Sep 17 00:00:00 2001 From: Kuldeep M Date: Thu, 9 Sep 2021 17:09:29 +0100 Subject: [PATCH 10/32] Workplace Search remove extraneous tooltip from Recent Activity table (#111709) * remove extraneous tooltip remove remove extraneous tooltip from Recent Activity table on the Source Overview page * remove unused import * rename trigger name to something more relevant --- .../shared/status_item/status_item.tsx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/status_item/status_item.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/status_item/status_item.tsx index 35ac8f1b85c05..025230d0b5c1a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/status_item/status_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/status_item/status_item.tsx @@ -11,7 +11,6 @@ import { EuiCopy, EuiButton, EuiButtonIcon, - EuiToolTip, EuiSpacer, EuiCodeBlock, EuiPopover, @@ -30,19 +29,17 @@ export const StatusItem: React.FC = ({ details }) => { const closePopover = () => setIsPopoverOpen(false); const formattedDetails = details.join('\n'); - const tooltipPopoverTrigger = ( - - - + const popoverTrigger = ( + ); const infoPopover = ( - + Date: Thu, 9 Sep 2021 12:14:39 -0400 Subject: [PATCH 11/32] [Event Log][8.0] Set all event log index assets to hidden (#110929) * Setting event log indices to hidden * Cleaning up cluster client and adding unit tests * Unit tests * Unit tests * Unit tests * Unit tests * PR feedback Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/es/cluster_client_adapter.mock.ts | 6 + .../server/es/cluster_client_adapter.test.ts | 287 +++++++++++++++- .../server/es/cluster_client_adapter.ts | 138 +++++++- .../event_log/server/es/context.test.ts | 1 + .../event_log/server/es/documents.test.ts | 11 +- .../plugins/event_log/server/es/documents.ts | 15 +- .../plugins/event_log/server/es/init.test.ts | 321 ++++++++++++++++++ x-pack/plugins/event_log/server/es/init.ts | 120 +++++++ 8 files changed, 875 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts index 8a33342e71d02..667512ea13f65 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.mock.ts @@ -17,6 +17,12 @@ const createClusterClientMock = () => { createIndexTemplate: jest.fn(), doesAliasExist: jest.fn(), createIndex: jest.fn(), + getExistingLegacyIndexTemplates: jest.fn(), + setLegacyIndexTemplateToHidden: jest.fn(), + getExistingIndices: jest.fn(), + setIndexToHidden: jest.fn(), + getExistingIndexAliases: jest.fn(), + setIndexAliasToHidden: jest.fn(), queryEventsBySavedObjects: jest.fn(), shutdown: jest.fn(), }; diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts index ef43b9081f9ec..f4140298928b6 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts @@ -16,7 +16,7 @@ import { findOptionsSchema } from '../event_log_client'; import { delay } from '../lib/delay'; import { times } from 'lodash'; import { DeeplyMockedKeys } from '@kbn/utility-types/jest'; -import { RequestEvent } from '@elastic/elasticsearch'; +import { estypes, RequestEvent } from '@elastic/elasticsearch'; type MockedLogger = ReturnType; @@ -215,22 +215,39 @@ describe('doesIndexTemplateExist', () => { }); }); - test('should return true when call cluster returns true', async () => { + test('should return true when call cluster to legacy template API returns true', async () => { clusterClient.indices.existsTemplate.mockResolvedValue(asApiResponse(true)); + clusterClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(false)); await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(true); }); - test('should return false when call cluster returns false', async () => { + test('should return true when call cluster to index template API returns true', async () => { clusterClient.indices.existsTemplate.mockResolvedValue(asApiResponse(false)); + clusterClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(true)); + await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(true); + }); + + test('should return false when both call cluster calls returns false', async () => { + clusterClient.indices.existsTemplate.mockResolvedValue(asApiResponse(false)); + clusterClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(false)); await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(false); }); - test('should throw error when call cluster throws an error', async () => { + test('should throw error when call cluster to legacy template API throws an error', async () => { clusterClient.indices.existsTemplate.mockRejectedValue(new Error('Fail')); await expect( clusterClientAdapter.doesIndexTemplateExist('foo') ).rejects.toThrowErrorMatchingInlineSnapshot( - `"error checking existance of index template: Fail"` + `"error checking existence of index template: Fail"` + ); + }); + + test('should throw error when call cluster to index template API throws an error', async () => { + clusterClient.indices.existsIndexTemplate.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.doesIndexTemplateExist('foo') + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error checking existence of index template: Fail"` ); }); }); @@ -238,7 +255,7 @@ describe('doesIndexTemplateExist', () => { describe('createIndexTemplate', () => { test('should call cluster with given template', async () => { await clusterClientAdapter.createIndexTemplate('foo', { args: true }); - expect(clusterClient.indices.putTemplate).toHaveBeenCalledWith({ + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ name: 'foo', create: true, body: { args: true }, @@ -246,20 +263,274 @@ describe('createIndexTemplate', () => { }); test(`should throw error if index template still doesn't exist after error is thrown`, async () => { - clusterClient.indices.putTemplate.mockRejectedValueOnce(new Error('Fail')); + clusterClient.indices.putIndexTemplate.mockRejectedValueOnce(new Error('Fail')); clusterClient.indices.existsTemplate.mockResolvedValueOnce(asApiResponse(false)); + clusterClient.indices.existsIndexTemplate.mockResolvedValueOnce(asApiResponse(false)); await expect( clusterClientAdapter.createIndexTemplate('foo', { args: true }) ).rejects.toThrowErrorMatchingInlineSnapshot(`"error creating index template: Fail"`); }); test('should not throw error if index template exists after error is thrown', async () => { - clusterClient.indices.putTemplate.mockRejectedValueOnce(new Error('Fail')); + clusterClient.indices.putIndexTemplate.mockRejectedValueOnce(new Error('Fail')); clusterClient.indices.existsTemplate.mockResolvedValueOnce(asApiResponse(true)); await clusterClientAdapter.createIndexTemplate('foo', { args: true }); }); }); +describe('getExistingLegacyIndexTemplates', () => { + test('should call cluster with given index template pattern', async () => { + await clusterClientAdapter.getExistingLegacyIndexTemplates('foo*'); + expect(clusterClient.indices.getTemplate).toHaveBeenCalledWith( + { + name: 'foo*', + }, + { ignore: [404] } + ); + }); + + test('should return templates when found', async () => { + const response = { + 'foo-bar-template': { + order: 0, + index_patterns: ['foo-bar-*'], + settings: { index: { number_of_shards: '1' } }, + mappings: { dynamic: false, properties: {} }, + aliases: {}, + }, + }; + clusterClient.indices.getTemplate.mockResolvedValue( + asApiResponse(response) + ); + await expect(clusterClientAdapter.getExistingLegacyIndexTemplates('foo*')).resolves.toEqual( + response + ); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.indices.getTemplate.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.getExistingLegacyIndexTemplates('foo*') + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error getting existing legacy index templates: Fail"` + ); + }); +}); + +describe('setLegacyIndexTemplateToHidden', () => { + test('should call cluster with given index template name and template', async () => { + const currentTemplate = { + order: 0, + index_patterns: ['foo-bar-*'], + settings: { index: { number_of_shards: '1' } }, + mappings: { dynamic: false, properties: {} }, + aliases: {}, + }; + await clusterClientAdapter.setLegacyIndexTemplateToHidden('foo-bar-template', currentTemplate); + expect(clusterClient.indices.putTemplate).toHaveBeenCalledWith({ + name: 'foo-bar-template', + body: { + order: 0, + index_patterns: ['foo-bar-*'], + settings: { index: { number_of_shards: '1' }, 'index.hidden': true }, + mappings: { dynamic: false, properties: {} }, + aliases: {}, + }, + }); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.indices.putTemplate.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.setLegacyIndexTemplateToHidden('foo-bar-template', { + aliases: {}, + index_patterns: [], + mappings: {}, + order: 0, + settings: {}, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error setting existing legacy index template foo-bar-template to hidden: Fail"` + ); + }); +}); + +describe('getExistingIndices', () => { + test('should call cluster with given index pattern', async () => { + await clusterClientAdapter.getExistingIndices('foo*'); + expect(clusterClient.indices.getSettings).toHaveBeenCalledWith( + { + index: 'foo*', + }, + { ignore: [404] } + ); + }); + + test('should return indices when found', async () => { + const response = { + 'foo-bar-000001': { + settings: { + index: { + number_of_shards: 1, + uuid: 'Ure4d9edQbCMtcmyy0ObrA', + }, + }, + }, + }; + clusterClient.indices.getSettings.mockResolvedValue( + asApiResponse(response) + ); + await expect(clusterClientAdapter.getExistingIndices('foo*')).resolves.toEqual(response); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.indices.getSettings.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.getExistingIndices('foo*') + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error getting existing indices matching pattern foo*: Fail"` + ); + }); +}); + +describe('setIndexToHidden', () => { + test('should call cluster with given index name', async () => { + await clusterClientAdapter.setIndexToHidden('foo-bar-000001'); + expect(clusterClient.indices.putSettings).toHaveBeenCalledWith({ + index: 'foo-bar-000001', + body: { + settings: { + 'index.hidden': true, + }, + }, + }); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.indices.putSettings.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.setIndexToHidden('foo-bar-000001') + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error setting existing index foo-bar-000001 to hidden: Fail"` + ); + }); +}); + +describe('getExistingIndexAliases', () => { + test('should call cluster with given index pattern', async () => { + await clusterClientAdapter.getExistingIndexAliases('foo*'); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith( + { + index: 'foo*', + }, + { ignore: [404] } + ); + }); + + test('should return aliases when found', async () => { + const response = { + 'foo-bar-000001': { + aliases: { + 'foo-bar': { + is_write_index: true, + }, + }, + }, + }; + clusterClient.indices.getAlias.mockResolvedValue( + asApiResponse(response) + ); + await expect(clusterClientAdapter.getExistingIndexAliases('foo*')).resolves.toEqual(response); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.indices.getAlias.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.getExistingIndexAliases('foo*') + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error getting existing index aliases matching pattern foo*: Fail"` + ); + }); +}); + +describe('setIndexAliasToHidden', () => { + test('should call cluster with given index name and aliases', async () => { + await clusterClientAdapter.setIndexAliasToHidden('foo-bar-000001', { + aliases: { + 'foo-bar': { + is_write_index: true, + }, + }, + }); + expect(clusterClient.indices.updateAliases).toHaveBeenCalledWith({ + body: { + actions: [ + { + add: { + index: 'foo-bar-000001', + alias: 'foo-bar', + is_hidden: true, + is_write_index: true, + }, + }, + ], + }, + }); + }); + + test('should update multiple aliases at once and preserve existing alias settings', async () => { + await clusterClientAdapter.setIndexAliasToHidden('foo-bar-000001', { + aliases: { + 'foo-bar': { + is_write_index: true, + }, + 'foo-b': { + index_routing: 'index', + routing: 'route', + }, + }, + }); + expect(clusterClient.indices.updateAliases).toHaveBeenCalledWith({ + body: { + actions: [ + { + add: { + index: 'foo-bar-000001', + alias: 'foo-bar', + is_hidden: true, + is_write_index: true, + }, + }, + { + add: { + index: 'foo-bar-000001', + alias: 'foo-b', + is_hidden: true, + index_routing: 'index', + routing: 'route', + }, + }, + ], + }, + }); + }); + + test('should throw error when call cluster throws an error', async () => { + clusterClient.indices.updateAliases.mockRejectedValue(new Error('Fail')); + await expect( + clusterClientAdapter.setIndexAliasToHidden('foo-bar-000001', { + aliases: { + 'foo-bar': { + is_write_index: true, + }, + }, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"error setting existing index aliases for index foo-bar-000001 to is_hidden: Fail"` + ); + }); +}); + describe('doesAliasExist', () => { test('should call cluster with proper arguments', async () => { await clusterClientAdapter.doesAliasExist('foo'); diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts index 47bd29cf4b08a..7eb3328dddb6b 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts @@ -7,7 +7,7 @@ import { Subject } from 'rxjs'; import { bufferTime, filter as rxFilter, switchMap } from 'rxjs/operators'; -import { reject, isUndefined, isNumber } from 'lodash'; +import { reject, isUndefined, isNumber, pick } from 'lodash'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { Logger, ElasticsearchClient } from 'src/core/server'; import util from 'util'; @@ -163,17 +163,23 @@ export class ClusterClientAdapter { try { const esClient = await this.elasticsearchClientPromise; - const { body } = await esClient.indices.existsTemplate({ name }); - return body as boolean; + const { body: legacyResult } = await esClient.indices.existsTemplate({ name }); + const { body: indexTemplateResult } = await esClient.indices.existsIndexTemplate({ name }); + return (legacyResult as boolean) || (indexTemplateResult as boolean); } catch (err) { - throw new Error(`error checking existance of index template: ${err.message}`); + throw new Error(`error checking existence of index template: ${err.message}`); } } public async createIndexTemplate(name: string, template: Record): Promise { try { const esClient = await this.elasticsearchClientPromise; - await esClient.indices.putTemplate({ name, body: template, create: true }); + await esClient.indices.putIndexTemplate({ + name, + body: template, + // @ts-expect-error doesn't exist in @elastic/elasticsearch + create: true, + }); } catch (err) { // The error message doesn't have a type attribute we can look to guarantee it's due // to the template already existing (only long message) so we'll check ourselves to see @@ -188,6 +194,128 @@ export class ClusterClientAdapter { + try { + const esClient = await this.elasticsearchClientPromise; + const { body: templates } = await esClient.indices.getTemplate( + { name: indexTemplatePattern }, + { ignore: [404] } + ); + return templates; + } catch (err) { + throw new Error(`error getting existing legacy index templates: ${err.message}`); + } + } + + public async setLegacyIndexTemplateToHidden( + indexTemplateName: string, + currentIndexTemplate: estypes.IndicesTemplateMapping + ): Promise { + try { + const esClient = await this.elasticsearchClientPromise; + await esClient.indices.putTemplate({ + name: indexTemplateName, + body: { + ...currentIndexTemplate, + settings: { + ...currentIndexTemplate.settings, + 'index.hidden': true, + }, + }, + }); + } catch (err) { + throw new Error( + `error setting existing legacy index template ${indexTemplateName} to hidden: ${err.message}` + ); + } + } + + public async getExistingIndices( + indexPattern: string + ): Promise { + try { + const esClient = await this.elasticsearchClientPromise; + const { body: indexSettings } = await esClient.indices.getSettings( + { index: indexPattern }, + { ignore: [404] } + ); + return indexSettings; + } catch (err) { + throw new Error( + `error getting existing indices matching pattern ${indexPattern}: ${err.message}` + ); + } + } + + public async setIndexToHidden(indexName: string): Promise { + try { + const esClient = await this.elasticsearchClientPromise; + await esClient.indices.putSettings({ + index: indexName, + body: { + settings: { + 'index.hidden': true, + }, + }, + }); + } catch (err) { + throw new Error(`error setting existing index ${indexName} to hidden: ${err.message}`); + } + } + + public async getExistingIndexAliases( + indexPattern: string + ): Promise { + try { + const esClient = await this.elasticsearchClientPromise; + const { body: indexAliases } = await esClient.indices.getAlias( + { index: indexPattern }, + { ignore: [404] } + ); + return indexAliases; + } catch (err) { + throw new Error( + `error getting existing index aliases matching pattern ${indexPattern}: ${err.message}` + ); + } + } + + public async setIndexAliasToHidden( + indexName: string, + currentAliases: estypes.IndicesGetAliasIndexAliases + ): Promise { + try { + const esClient = await this.elasticsearchClientPromise; + await esClient.indices.updateAliases({ + body: { + actions: Object.keys(currentAliases.aliases).map((aliasName) => { + const existingAliasOptions = pick(currentAliases.aliases[aliasName], [ + 'is_write_index', + 'filter', + 'index_routing', + 'routing', + 'search_routing', + ]); + return { + add: { + ...existingAliasOptions, + index: indexName, + alias: aliasName, + is_hidden: true, + }, + }; + }), + }, + }); + } catch (err) { + throw new Error( + `error setting existing index aliases for index ${indexName} to is_hidden: ${err.message}` + ); + } + } + public async doesAliasExist(name: string): Promise { try { const esClient = await this.elasticsearchClientPromise; diff --git a/x-pack/plugins/event_log/server/es/context.test.ts b/x-pack/plugins/event_log/server/es/context.test.ts index 9589ab3c4aebf..0fe63ffb6217a 100644 --- a/x-pack/plugins/event_log/server/es/context.test.ts +++ b/x-pack/plugins/event_log/server/es/context.test.ts @@ -64,6 +64,7 @@ describe('createEsContext', () => { elasticsearchClientPromise: Promise.resolve(elasticsearchClient), }); elasticsearchClient.indices.existsTemplate.mockResolvedValue(asApiResponse(false)); + elasticsearchClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(false)); elasticsearchClient.indices.existsAlias.mockResolvedValue(asApiResponse(false)); const doesAliasExist = await context.esAdapter.doesAliasExist(context.esNames.alias); expect(doesAliasExist).toBeFalsy(); diff --git a/x-pack/plugins/event_log/server/es/documents.test.ts b/x-pack/plugins/event_log/server/es/documents.test.ts index 121fcc42f37e4..6df5a1334f167 100644 --- a/x-pack/plugins/event_log/server/es/documents.test.ts +++ b/x-pack/plugins/event_log/server/es/documents.test.ts @@ -25,10 +25,11 @@ describe('getIndexTemplate()', () => { test('returns the correct details of the index template', () => { const indexTemplate = getIndexTemplate(esNames); expect(indexTemplate.index_patterns).toEqual([esNames.indexPatternWithVersion]); - expect(indexTemplate.settings.number_of_shards).toBeGreaterThanOrEqual(0); - expect(indexTemplate.settings.auto_expand_replicas).toBe('0-1'); - expect(indexTemplate.settings['index.lifecycle.name']).toBe(esNames.ilmPolicy); - expect(indexTemplate.settings['index.lifecycle.rollover_alias']).toBe(esNames.alias); - expect(indexTemplate.mappings).toMatchObject({}); + expect(indexTemplate.template.settings.number_of_shards).toBeGreaterThanOrEqual(0); + expect(indexTemplate.template.settings.auto_expand_replicas).toBe('0-1'); + expect(indexTemplate.template.settings['index.lifecycle.name']).toBe(esNames.ilmPolicy); + expect(indexTemplate.template.settings['index.lifecycle.rollover_alias']).toBe(esNames.alias); + expect(indexTemplate.template.settings['index.hidden']).toBe(true); + expect(indexTemplate.template.mappings).toMatchObject({}); }); }); diff --git a/x-pack/plugins/event_log/server/es/documents.ts b/x-pack/plugins/event_log/server/es/documents.ts index 8594fca603d18..c4ffda5f51ebe 100644 --- a/x-pack/plugins/event_log/server/es/documents.ts +++ b/x-pack/plugins/event_log/server/es/documents.ts @@ -12,13 +12,16 @@ import mappings from '../../generated/mappings.json'; export function getIndexTemplate(esNames: EsNames) { const indexTemplateBody = { index_patterns: [esNames.indexPatternWithVersion], - settings: { - number_of_shards: 1, - auto_expand_replicas: '0-1', - 'index.lifecycle.name': esNames.ilmPolicy, - 'index.lifecycle.rollover_alias': esNames.alias, + template: { + settings: { + number_of_shards: 1, + auto_expand_replicas: '0-1', + 'index.lifecycle.name': esNames.ilmPolicy, + 'index.lifecycle.rollover_alias': esNames.alias, + 'index.hidden': true, + }, + mappings, }, - mappings, }; return indexTemplateBody; diff --git a/x-pack/plugins/event_log/server/es/init.test.ts b/x-pack/plugins/event_log/server/es/init.test.ts index 074ceea1f4a24..bfdf0c17e5035 100644 --- a/x-pack/plugins/event_log/server/es/init.test.ts +++ b/x-pack/plugins/event_log/server/es/init.test.ts @@ -13,6 +13,327 @@ describe('initializeEs', () => { beforeEach(() => { esContext = contextMock.create(); + esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({}); + esContext.esAdapter.getExistingIndices.mockResolvedValue({}); + esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({}); + }); + + test(`should update existing index templates if any exist and are not hidden`, async () => { + const testTemplate = { + order: 0, + index_patterns: ['foo-bar-*'], + settings: { + index: { + lifecycle: { + name: 'foo-bar-policy', + rollover_alias: 'foo-bar-1', + }, + number_of_shards: '1', + auto_expand_replicas: '0-1', + }, + }, + mappings: {}, + aliases: {}, + }; + esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({ + 'foo-bar-template': testTemplate, + }); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled(); + expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).toHaveBeenCalledWith( + 'foo-bar-template', + testTemplate + ); + }); + + test(`should not update existing index templates if any exist and are already hidden`, async () => { + const testTemplate = { + order: 0, + index_patterns: ['foo-bar-*'], + settings: { + index: { + lifecycle: { + name: 'foo-bar-policy', + rollover_alias: 'foo-bar-1', + }, + hidden: 'true', + number_of_shards: '1', + auto_expand_replicas: '0-1', + }, + }, + mappings: {}, + aliases: {}, + }; + esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({ + 'foo-bar-template': testTemplate, + }); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled(); + expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled(); + }); + + test(`should continue initialization if getting existing index templates throws an error`, async () => { + esContext.esAdapter.getExistingLegacyIndexTemplates.mockRejectedValue(new Error('Fail')); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled(); + expect(esContext.logger.error).toHaveBeenCalledWith( + `error getting existing index templates - Fail` + ); + expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled(); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); + }); + + test(`should continue initialization if updating existing index templates throws an error`, async () => { + const testTemplate = { + order: 0, + index_patterns: ['foo-bar-*'], + settings: { + index: { + lifecycle: { + name: 'foo-bar-policy', + rollover_alias: 'foo-bar-1', + }, + number_of_shards: '1', + auto_expand_replicas: '0-1', + }, + }, + mappings: {}, + aliases: {}, + }; + esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({ + 'foo-bar-template': testTemplate, + 'another-test-template': testTemplate, + }); + esContext.esAdapter.setLegacyIndexTemplateToHidden.mockRejectedValueOnce(new Error('Fail')); + esContext.esAdapter.setLegacyIndexTemplateToHidden.mockResolvedValueOnce(); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled(); + expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).toHaveBeenCalledWith( + 'foo-bar-template', + testTemplate + ); + expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).toHaveBeenCalledWith( + 'another-test-template', + testTemplate + ); + expect(esContext.logger.error).toHaveBeenCalledTimes(1); + expect(esContext.logger.error).toHaveBeenCalledWith( + `error setting existing \"foo-bar-template\" index template to hidden - Fail` + ); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); + }); + + test(`should update existing index settings if any exist and are not hidden`, async () => { + const testSettings = { + settings: { + index: { + lifecycle: { + name: 'foo-bar-policy', + rollover_alias: 'foo-bar-1', + }, + routing: { + allocation: { + include: { + _tier_preference: 'data_content', + }, + }, + }, + number_of_shards: '1', + auto_expand_replicas: '0-1', + provided_name: '.kibana-event-log-7.15.0-000001', + creation_date: '1630439186791', + number_of_replicas: '0', + uuid: 'Ure4d9edQbCMtcmyy0ObrA', + version: { + created: '7150099', + }, + }, + }, + }; + esContext.esAdapter.getExistingIndices.mockResolvedValue({ + 'foo-bar-000001': testSettings, + }); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexToHidden).toHaveBeenCalledWith('foo-bar-000001'); + }); + + test(`should not update existing index settings if any exist and are already hidden`, async () => { + const testSettings = { + settings: { + index: { + lifecycle: { + name: 'foo-bar-policy', + rollover_alias: 'foo-bar-1', + }, + routing: { + allocation: { + include: { + _tier_preference: 'data_content', + }, + }, + }, + hidden: 'true', + number_of_shards: '1', + auto_expand_replicas: '0-1', + provided_name: '.kibana-event-log-7.15.0-000001', + creation_date: '1630439186791', + number_of_replicas: '0', + uuid: 'Ure4d9edQbCMtcmyy0ObrA', + version: { + created: '7150099', + }, + }, + }, + }; + esContext.esAdapter.getExistingIndices.mockResolvedValue({ + 'foo-bar-000001': testSettings, + }); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled(); + }); + + test(`should continue initialization if getting existing index settings throws an error`, async () => { + esContext.esAdapter.getExistingIndices.mockRejectedValue(new Error('Fail')); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled(); + expect(esContext.logger.error).toHaveBeenCalledWith(`error getting existing indices - Fail`); + expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled(); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); + }); + + test(`should continue initialization if updating existing index settings throws an error`, async () => { + const testSettings = { + settings: { + index: { + lifecycle: { + name: 'foo-bar-policy', + rollover_alias: 'foo-bar-1', + }, + routing: { + allocation: { + include: { + _tier_preference: 'data_content', + }, + }, + }, + number_of_shards: '1', + auto_expand_replicas: '0-1', + provided_name: '.kibana-event-log-7.15.0-000001', + creation_date: '1630439186791', + number_of_replicas: '0', + uuid: 'Ure4d9edQbCMtcmyy0ObrA', + version: { + created: '7150099', + }, + }, + }, + }; + esContext.esAdapter.getExistingIndices.mockResolvedValue({ + 'foo-bar-000001': testSettings, + 'foo-bar-000002': testSettings, + }); + + esContext.esAdapter.setIndexToHidden.mockRejectedValueOnce(new Error('Fail')); + esContext.esAdapter.setIndexToHidden.mockResolvedValueOnce(); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled(); + expect(esContext.logger.error).toHaveBeenCalledTimes(1); + expect(esContext.logger.error).toHaveBeenCalledWith( + `error setting existing \"foo-bar-000001\" index to hidden - Fail` + ); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); + }); + + test(`should update existing index aliases if any exist and are not hidden`, async () => { + const testAliases = { + aliases: { + 'foo-bar': { + is_write_index: true, + }, + }, + }; + esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({ + 'foo-bar-000001': testAliases, + }); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexAliasToHidden).toHaveBeenCalledWith( + 'foo-bar-000001', + testAliases + ); + }); + + test(`should not update existing index aliases if any exist and are already hidden`, async () => { + const testAliases = { + aliases: { + 'foo-bar': { + is_write_index: true, + is_hidden: true, + }, + }, + }; + esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({ + 'foo-bar-000001': testAliases, + }); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled(); + }); + + test(`should continue initialization if getting existing index aliases throws an error`, async () => { + esContext.esAdapter.getExistingIndexAliases.mockRejectedValue(new Error('Fail')); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled(); + expect(esContext.logger.error).toHaveBeenCalledWith( + `error getting existing index aliases - Fail` + ); + expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled(); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); + }); + + test(`should continue initialization if updating existing index aliases throws an error`, async () => { + const testAliases = { + aliases: { + 'foo-bar': { + is_write_index: true, + }, + }, + }; + esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({ + 'foo-bar-000001': testAliases, + 'foo-bar-000002': testAliases, + }); + esContext.esAdapter.setIndexAliasToHidden.mockRejectedValueOnce(new Error('Fail')); + esContext.esAdapter.setIndexAliasToHidden.mockResolvedValueOnce(); + + await initializeEs(esContext); + expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled(); + expect(esContext.esAdapter.setIndexAliasToHidden).toHaveBeenCalledWith( + 'foo-bar-000001', + testAliases + ); + expect(esContext.esAdapter.setIndexAliasToHidden).toHaveBeenCalledWith( + 'foo-bar-000002', + testAliases + ); + expect(esContext.logger.error).toHaveBeenCalledTimes(1); + expect(esContext.logger.error).toHaveBeenCalledWith( + `error setting existing \"foo-bar-000001\" index aliases - Fail` + ); + expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled(); }); test(`should create ILM policy if it doesn't exist`, async () => { diff --git a/x-pack/plugins/event_log/server/es/init.ts b/x-pack/plugins/event_log/server/es/init.ts index 484dfdc95a72c..e2769e39b28ff 100644 --- a/x-pack/plugins/event_log/server/es/init.ts +++ b/x-pack/plugins/event_log/server/es/init.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { IndicesAlias, IndicesIndexStatePrefixedSettings } from '@elastic/elasticsearch/api/types'; +import { estypes } from '@elastic/elasticsearch'; import { getIlmPolicy, getIndexTemplate } from './documents'; import { EsContext } from './context'; @@ -25,6 +27,7 @@ export async function initializeEs(esContext: EsContext): Promise { async function initializeEsResources(esContext: EsContext) { const steps = new EsInitializationSteps(esContext); + await steps.setExistingAssetsToHidden(); await steps.createIlmPolicyIfNotExists(); await steps.createIndexTemplateIfNotExists(); await steps.createInitialIndexIfNotExists(); @@ -35,6 +38,122 @@ class EsInitializationSteps { this.esContext = esContext; } + async setExistingIndexTemplatesToHidden() { + let indexTemplates: estypes.IndicesGetTemplateResponse = {}; + try { + // look up existing index templates and update index.hidden to true if that + // setting is currently false or undefined + + // since we are updating to the new index template API and converting new event log + // indices to hidden in the same PR, we only need to use the legacy template API to + // look for and update existing event log indices. + indexTemplates = await this.esContext.esAdapter.getExistingLegacyIndexTemplates( + this.esContext.esNames.indexPattern + ); + } catch (err) { + // errors when trying to get existing index templates + // should not block the rest of initialization, log the error and move on + this.esContext.logger.error(`error getting existing index templates - ${err.message}`); + } + + Object.keys(indexTemplates).forEach(async (indexTemplateName: string) => { + try { + const hidden: string | boolean = indexTemplates[indexTemplateName]?.settings?.index?.hidden; + // Check to see if this index template is hidden + if (hidden !== true && hidden !== 'true') { + this.esContext.logger.debug( + `setting existing "${indexTemplateName}" index template to hidden.` + ); + + await this.esContext.esAdapter.setLegacyIndexTemplateToHidden( + indexTemplateName, + indexTemplates[indexTemplateName] + ); + } + } catch (err) { + // errors when trying to update existing index templates to hidden + // should not block the rest of initialization, log the error and move on + this.esContext.logger.error( + `error setting existing "${indexTemplateName}" index template to hidden - ${err.message}` + ); + } + }); + } + + async setExistingIndicesToHidden() { + let indices: estypes.IndicesGetSettingsResponse = {}; + try { + // look up existing indices and update index.hidden to true if that + // setting is currently false or undefined + indices = await this.esContext.esAdapter.getExistingIndices( + this.esContext.esNames.indexPattern + ); + } catch (err) { + // errors when trying to get existing indices + // should not block the rest of initialization, log the error and move on + this.esContext.logger.error(`error getting existing indices - ${err.message}`); + } + + Object.keys(indices).forEach(async (indexName: string) => { + try { + const hidden: string | boolean | undefined = (indices[indexName] + ?.settings as IndicesIndexStatePrefixedSettings)?.index?.hidden; + + // Check to see if this index template is hidden + if (hidden !== true && hidden !== 'true') { + this.esContext.logger.debug(`setting existing ${indexName} index to hidden.`); + await this.esContext.esAdapter.setIndexToHidden(indexName); + } + } catch (err) { + // errors when trying to update existing indices to hidden + // should not block the rest of initialization, log the error and move on + this.esContext.logger.error( + `error setting existing "${indexName}" index to hidden - ${err.message}` + ); + } + }); + } + + async setExistingIndexAliasesToHidden() { + let indexAliases: estypes.IndicesGetAliasResponse = {}; + try { + // Look up existing index aliases and update index.is_hidden to true if that + // setting is currently false or undefined + indexAliases = await this.esContext.esAdapter.getExistingIndexAliases( + this.esContext.esNames.indexPattern + ); + } catch (err) { + // errors when trying to get existing index aliases + // should not block the rest of initialization, log the error and move on + this.esContext.logger.error(`error getting existing index aliases - ${err.message}`); + } + Object.keys(indexAliases).forEach(async (indexName: string) => { + try { + const aliases = indexAliases[indexName]?.aliases; + const hasNotHiddenAliases: boolean = Object.keys(aliases).some((alias: string) => { + return (aliases[alias] as IndicesAlias)?.is_hidden !== true; + }); + + if (hasNotHiddenAliases) { + this.esContext.logger.debug(`setting existing "${indexName}" index aliases to hidden.`); + await this.esContext.esAdapter.setIndexAliasToHidden(indexName, indexAliases[indexName]); + } + } catch (err) { + // errors when trying to set existing index aliases to is_hidden + // should not block the rest of initialization, log the error and move on + this.esContext.logger.error( + `error setting existing "${indexName}" index aliases - ${err.message}` + ); + } + }); + } + + async setExistingAssetsToHidden(): Promise { + await this.setExistingIndexTemplatesToHidden(); + await this.setExistingIndicesToHidden(); + await this.setExistingIndexAliasesToHidden(); + } + async createIlmPolicyIfNotExists(): Promise { const exists = await this.esContext.esAdapter.doesIlmPolicyExist( this.esContext.esNames.ilmPolicy @@ -67,6 +186,7 @@ class EsInitializationSteps { aliases: { [this.esContext.esNames.alias]: { is_write_index: true, + is_hidden: true, }, }, }); From b546762668c86603c9ed0d55d6b0b7e098849a10 Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Thu, 9 Sep 2021 11:44:22 -0500 Subject: [PATCH 12/32] [DOCS] Adds preview to runtime fields (#110327) * [DOCS] Adds preview to runtime fields * Final draft changes * Review comments --- ...ent-indexPatterns-pinRuntimeField-7.15.png | Bin 0 -> 4334 bytes .../management/manage-index-patterns.asciidoc | 46 +++++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 docs/management/images/stackManagement-indexPatterns-pinRuntimeField-7.15.png diff --git a/docs/management/images/stackManagement-indexPatterns-pinRuntimeField-7.15.png b/docs/management/images/stackManagement-indexPatterns-pinRuntimeField-7.15.png new file mode 100644 index 0000000000000000000000000000000000000000..49d0d4caec00f8dd1c3cd246dbfabe07104fdc51 GIT binary patch literal 4334 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%0DOst7C-g{?_m zT=*C1-;V!EwD_ASCizd|KOFxcUKIc~@I_!(>2S4!@*)t>|FQiWZv;bmdH7$!O_2yc zdC^~#f0=)=AfT&5`Ntvs?0_FuYzxQ}LqNaVNuHSTRQ(mU`JQR1Dw$}K)tL0VQ!CM2 z1V~vXduCX0xt>sH=B?-rCyXSsDc|GUUkK0rte^y9p;78>i6Y#YeJ!VIeV59R^75Md z`)Uq#KJKs1;V07`QrVmOQl{H2>pgw%w=$2Kg2XcBPuMS_7s=;H+bAbLrWYY*Q^h4j zb{2gJ_N&9GD5l5vqCSVjKYuAs3e4^^sGjhILU6NGeUqA4bInQ}g6mWJ5+zb626mMD zDcWSwTRy^06N~(#t=aY;@MAF|=6sGL2`?|+zl-}i?EhKc?62c6(K{H}bdSUN0ikpv z&~};haMGy#2@QB@b$NU4n1C-u3%CC6gQ@E|EopD8>uUUf9gf$Pl;L`&NZs-^f{b2n zBxtJrm?Z5EMJ%T;_tf}BWWt_5By1l_DW)!|&E~nTYN4ygOq&2+zJ24*FJCc+w+-@5 zDtX6M>lPYV*&~Bif}XgZIS@m@|vGqq-nxuD;TG% zu=cAM>aWAMTit3ochbG^^Mw5hbozIan#xcKWMs)@{FV{KQk&pT0uJH z(x{F^uP1jE2}pfaVllA5KbAtBnYZW2H<>n(ykaKT>-poYU8B-F8#;+nj^yQM{YC3+ xkN0GP16LO6_AB>cJ$amP7d{^L4r!yqb0EeNQR*xkarHL_XsPL|mMh> and <>. . Open the main menu, then click *Stack Management > Index Patterns*. . Select the index pattern you want to add the runtime field to, then click *Add field*. -. Enter a *Name* for the runtime field, then select the field *Type*. +. Enter the field *Name*, then select the *Type*. + +. Select *Set custom label*, then enter the label you want to display where the index pattern is used, such as *Discover*. + +. Select *Set value*, then define the script. The script must match the *Type*, or the index pattern fails anywhere it is used. + +. To help you define the script, use the *Preview*: + +* To view the other available fields, use the *Document ID* arrows. + +* To filter the fields list, enter the keyword in *Filter fields*. -. Select *Set value*, then define the field value by emitting a single value using the {ref}/modules-scripting-painless.html[Painless scripting language]. -+ -The script must match the field *Type*, or the script fails. +* To pin frequently used fields to the top of the list, hover over the field, then click image:images/stackManagement-indexPatterns-pinRuntimeField-7.15.png[Icon to pin field to the top of the list]. . Click *Create field*. -+ -For information on how to create runtime fields in *Discover*, refer to <>. -+ -For information on how to create runtime fields in *Lens*, refer to <>. [float] [[runtime-field-examples]] ==== Runtime field examples -Try the runtime field examples on your own using the *Sample web logs* data index pattern. +Try the runtime field examples on your own using the <> data index pattern. [float] [[simple-hello-world-example]] ==== Return a keyword value -To return `Hello World!` value: +Return `Hello World!`: [source,text] ---- @@ -101,7 +101,7 @@ emit(""); [[replace-nulls-with-blanks]] ===== Replace nulls with blanks -Replace null values with none values: +Replace `null` values with `None`: [source,text] ---- @@ -115,7 +115,7 @@ else { } ---- -Specify operating system condition: +Specify the operating system condition: [source,text] ---- From b9e6f935c44ec9092644e905bfd6b0c8e7ae2aad Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Thu, 9 Sep 2021 12:51:39 -0400 Subject: [PATCH 13/32] [Actions] Treat failures as successes for Task Manager (#109655) * Support retry with email as an example * Fix tests * Add logic to treat as failure if there is a retry * Handle retry better * Make this optional * Tweaks * Remove unnecessary code * Fix existing tests * Add some unit tests * Add test * Add doc note * More docs * PR feedback * Update docs/management/action-types.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/management/action-types.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/management/action-types.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/management/action-types.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/management/action-types.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/management/action-types.asciidoc | 9 ++ .../task-manager-health-monitoring.asciidoc | 9 ++ .../actions/server/action_type_registry.ts | 3 +- .../server/lib/action_executor.test.ts | 2 + .../actions/server/lib/action_executor.ts | 2 + .../server/lib/task_runner_factory.test.ts | 153 +++++++++++++++++- .../actions/server/lib/task_runner_factory.ts | 44 +++-- x-pack/plugins/actions/server/types.ts | 2 + .../alerting_api_integration/common/config.ts | 1 + .../plugins/alerts/server/action_types.ts | 37 +++++ .../spaces_only/tests/actions/enqueue.ts | 89 ++++++++-- 11 files changed, 324 insertions(+), 27 deletions(-) diff --git a/docs/management/action-types.asciidoc b/docs/management/action-types.asciidoc index 3d3d7aeb2d777..92adbaf97d8c5 100644 --- a/docs/management/action-types.asciidoc +++ b/docs/management/action-types.asciidoc @@ -135,5 +135,14 @@ image::images/connectors-with-missing-secrets.png[Connectors with missing secret For out-of-the-box and standardized connectors, you can <> before {kib} starts. +[float] +[[montoring-connectors]] +=== Monitoring connectors + +The <> helps you understand the performance of all tasks in your environment. +However, if connectors fail to execute, they will report as successful to Task Manager. The failure stats will not +accurately depict the performance of connectors. + +For more information on connector successes and failures, refer to the <>. include::connectors/index.asciidoc[] diff --git a/docs/user/production-considerations/task-manager-health-monitoring.asciidoc b/docs/user/production-considerations/task-manager-health-monitoring.asciidoc index 3321a9d0c02a1..b07a01906b895 100644 --- a/docs/user/production-considerations/task-manager-health-monitoring.asciidoc +++ b/docs/user/production-considerations/task-manager-health-monitoring.asciidoc @@ -111,6 +111,7 @@ a| Runtime | This section tracks excution performance of Task Manager, tracking task _drift_, worker _load_, and execution stats broken down by type, including duration and execution results. + a| Capacity Estimation | This section provides a rough estimate about the sufficiency of its capacity. As the name suggests, these are estimates based on historical data and should not be used as predictions. Use these estimations when following the Task Manager <>. @@ -123,6 +124,14 @@ The root `status` indicates the `status` of the system overall. The Runtime `status` indicates whether task executions have exceeded any of the <>. An `OK` status means none of the threshold have been exceeded. A `Warning` status means that at least one warning threshold has been exceeded. An `Error` status means that at least one error threshold has been exceeded. +[IMPORTANT] +============================================== +Some tasks (such as <>) will incorrectly report their status as successful even if the task failed. +The runtime and workload block will return data about success and failures and will not take this into consideration. + +To get a better sense of action failures, please refer to the <> for more accurate context into failures and successes. +============================================== + The Capacity Estimation `status` indicates the sufficiency of the observed capacity. An `OK` status means capacity is sufficient. A `Warning` status means that capacity is sufficient for the scheduled recurring tasks, but non-recurring tasks often cause the cluster to exceed capacity. An `Error` status means that there is insufficient capacity across all types of tasks. By monitoring the `status` of the system overall, and the `status` of specific task types of interest, you can evaluate the health of the {kib} Task Management system. diff --git a/x-pack/plugins/actions/server/action_type_registry.ts b/x-pack/plugins/actions/server/action_type_registry.ts index e5846560a6c98..76b360ce8b17f 100644 --- a/x-pack/plugins/actions/server/action_type_registry.ts +++ b/x-pack/plugins/actions/server/action_type_registry.ts @@ -134,7 +134,8 @@ export class ActionTypeRegistry { // Don't retry other kinds of errors return false; }, - createTaskRunner: (context: RunContext) => this.taskRunnerFactory.create(context), + createTaskRunner: (context: RunContext) => + this.taskRunnerFactory.create(context, actionType.maxAttempts), }, }); // No need to notify usage on basic action types 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 440de161490aa..ba7f750859d40 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -187,10 +187,12 @@ test('successfully executes as a task', async () => { const scheduleDelay = 10000; // milliseconds const scheduled = new Date(Date.now() - scheduleDelay); + const attempts = 1; await actionExecutor.execute({ ...executeParams, taskInfo: { scheduled, + attempts, }, }); diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 5dfe56cff5016..d265bca237c3b 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -44,6 +44,7 @@ export interface ActionExecutorContext { export interface TaskInfo { scheduled: Date; + attempts: number; } export interface ExecuteOptions { @@ -210,6 +211,7 @@ export class ActionExecutor { config: validatedConfig, secrets: validatedSecrets, isEphemeral, + taskInfo, }); } catch (err) { rawResult = { 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 cff92f874e0ef..85d819ba09b8a 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 @@ -136,6 +136,7 @@ test('executes the task by calling the executor with proper parameters, using gi }), taskInfo: { scheduled: new Date(), + attempts: 0, }, }); @@ -191,6 +192,7 @@ test('executes the task by calling the executor with proper parameters, using st }), taskInfo: { scheduled: new Date(), + attempts: 0, }, }); @@ -341,6 +343,7 @@ test('uses API key when provided', async () => { }), taskInfo: { scheduled: new Date(), + attempts: 0, }, }); @@ -401,6 +404,7 @@ test('uses relatedSavedObjects merged with references when provided', async () = }), taskInfo: { scheduled: new Date(), + attempts: 0, }, }); }); @@ -451,6 +455,7 @@ test('uses relatedSavedObjects as is when references are empty', async () => { }), taskInfo: { scheduled: new Date(), + attempts: 0, }, }); }); @@ -499,6 +504,7 @@ test('sanitizes invalid relatedSavedObjects when provided', async () => { relatedSavedObjects: [], taskInfo: { scheduled: new Date(), + attempts: 0, }, }); }); @@ -538,6 +544,7 @@ test(`doesn't use API key when not provided`, async () => { }), taskInfo: { scheduled: new Date(), + attempts: 0, }, }); @@ -549,9 +556,15 @@ test(`doesn't use API key when not provided`, async () => { }); test(`throws an error when license doesn't support the action type`, async () => { - const taskRunner = taskRunnerFactory.create({ - taskInstance: mockedTaskInstance, - }); + const taskRunner = taskRunnerFactory.create( + { + taskInstance: { + ...mockedTaskInstance, + attempts: 1, + }, + }, + 2 + ); mockedEncryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ id: '3', @@ -579,6 +592,138 @@ test(`throws an error when license doesn't support the action type`, async () => } catch (e) { expect(e instanceof ExecutorError).toEqual(true); expect(e.data).toEqual({}); - expect(e.retry).toEqual(false); + expect(e.retry).toEqual(true); } }); + +test(`treats errors as errors if the task is retryable`, async () => { + const taskRunner = taskRunnerFactory.create({ + taskInstance: { + ...mockedTaskInstance, + attempts: 0, + }, + }); + + mockedEncryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ + id: '3', + type: 'action_task_params', + attributes: { + actionId: '2', + params: { baz: true }, + apiKey: Buffer.from('123:abc').toString('base64'), + }, + references: [ + { + id: '2', + name: 'actionRef', + type: 'action', + }, + ], + }); + mockedActionExecutor.execute.mockResolvedValueOnce({ + status: 'error', + actionId: '2', + message: 'Error message', + data: { foo: true }, + retry: false, + }); + + let err; + try { + await taskRunner.run(); + } catch (e) { + err = e; + } + expect(err).toBeDefined(); + expect(err instanceof ExecutorError).toEqual(true); + expect(err.data).toEqual({ foo: true }); + expect(err.retry).toEqual(false); + expect(taskRunnerFactoryInitializerParams.logger.error as jest.Mock).toHaveBeenCalledWith( + `Action '2' failed and will not retry: Error message` + ); +}); + +test(`treats errors as successes if the task is not retryable`, async () => { + const taskRunner = taskRunnerFactory.create({ + taskInstance: { + ...mockedTaskInstance, + attempts: 1, + }, + }); + + mockedEncryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ + id: '3', + type: 'action_task_params', + attributes: { + actionId: '2', + params: { baz: true }, + apiKey: Buffer.from('123:abc').toString('base64'), + }, + references: [ + { + id: '2', + name: 'actionRef', + type: 'action', + }, + ], + }); + mockedActionExecutor.execute.mockResolvedValueOnce({ + status: 'error', + actionId: '2', + message: 'Error message', + data: { foo: true }, + retry: false, + }); + + let err; + try { + await taskRunner.run(); + } catch (e) { + err = e; + } + expect(err).toBeUndefined(); + expect(taskRunnerFactoryInitializerParams.logger.error as jest.Mock).toHaveBeenCalledWith( + `Action '2' failed and will not retry: Error message` + ); +}); + +test('treats errors as errors if the error is thrown instead of returned', async () => { + const taskRunner = taskRunnerFactory.create({ + taskInstance: { + ...mockedTaskInstance, + attempts: 0, + }, + }); + + mockedEncryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ + id: '3', + type: 'action_task_params', + attributes: { + actionId: '2', + params: { baz: true }, + apiKey: Buffer.from('123:abc').toString('base64'), + }, + references: [ + { + id: '2', + name: 'actionRef', + type: 'action', + }, + ], + }); + mockedActionExecutor.execute.mockRejectedValueOnce({}); + + let err; + try { + await taskRunner.run(); + } catch (e) { + err = e; + } + expect(err).toBeDefined(); + expect(err instanceof ExecutorError).toEqual(true); + expect(err.data).toEqual({}); + expect(err.retry).toEqual(true); + expect(taskRunnerFactoryInitializerParams.logger.error as jest.Mock).toHaveBeenCalledWith( + `Action '2' failed and will retry: undefined` + ); +}); diff --git a/x-pack/plugins/actions/server/lib/task_runner_factory.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.ts index 45ae6c1d5fae9..9a3856bbf7cee 100644 --- a/x-pack/plugins/actions/server/lib/task_runner_factory.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.ts @@ -22,7 +22,6 @@ import { ActionExecutorContract } from './action_executor'; import { ExecutorError } from './executor_error'; import { RunContext } from '../../../task_manager/server'; import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server'; -import { ActionTypeDisabledError } from './errors'; import { ActionTaskParams, ActionTypeRegistryContract, @@ -62,7 +61,7 @@ export class TaskRunnerFactory { this.taskRunnerContext = taskRunnerContext; } - public create({ taskInstance }: RunContext) { + public create({ taskInstance }: RunContext, maxAttempts: number = 1) { if (!this.isInitialized) { throw new Error('TaskRunnerFactory not initialized'); } @@ -78,6 +77,7 @@ export class TaskRunnerFactory { const taskInfo = { scheduled: taskInstance.runAt, + attempts: taskInstance.attempts, }; return { @@ -119,7 +119,14 @@ export class TaskRunnerFactory { basePathService.set(fakeRequest, path); - let executorResult: ActionTypeExecutorResult; + // Throwing an executor error means we will attempt to retry the task + // TM will treat a task as a failure if `attempts >= maxAttempts` + // so we need to handle that here to avoid TM persisting the failed task + const isRetryableBasedOnAttempts = taskInfo.attempts < (maxAttempts ?? 1); + const willRetryMessage = `and will retry`; + const willNotRetryMessage = `and will not retry`; + + let executorResult: ActionTypeExecutorResult | undefined; try { executorResult = await actionExecutor.execute({ params, @@ -131,20 +138,39 @@ export class TaskRunnerFactory { relatedSavedObjects: validatedRelatedSavedObjects(logger, relatedSavedObjects), }); } catch (e) { - if (e instanceof ActionTypeDisabledError) { - // We'll stop re-trying due to action being forbidden - throw new ExecutorError(e.message, {}, false); + logger.error( + `Action '${actionId}' failed ${ + isRetryableBasedOnAttempts ? willRetryMessage : willNotRetryMessage + }: ${e.message}` + ); + if (isRetryableBasedOnAttempts) { + // In order for retry to work, we need to indicate to task manager this task + // failed + throw new ExecutorError(e.message, {}, true); } - throw e; } - if (executorResult.status === 'error') { + if ( + executorResult && + executorResult?.status === 'error' && + executorResult?.retry !== undefined && + isRetryableBasedOnAttempts + ) { + logger.error( + `Action '${actionId}' failed ${ + !!executorResult.retry ? willRetryMessage : willNotRetryMessage + }: ${executorResult.message}` + ); // Task manager error handler only kicks in when an error thrown (at this time) // So what we have to do is throw when the return status is `error`. throw new ExecutorError( executorResult.message, executorResult.data, - executorResult.retry == null ? false : executorResult.retry + executorResult.retry as boolean | Date + ); + } else if (executorResult && executorResult?.status === 'error') { + logger.error( + `Action '${actionId}' failed ${willNotRetryMessage}: ${executorResult.message}` ); } diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index 14e9e120a853a..64250ca77fba4 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -19,6 +19,7 @@ import { SavedObjectReference, } from '../../../../src/core/server'; import { ActionTypeExecutorResult } from '../common'; +import { TaskInfo } from './lib/action_executor'; export { ActionTypeExecutorResult } from '../common'; export { GetFieldsByIssueTypeResponse as JiraGetFieldsResponse } from './builtin_action_types/jira/types'; export { GetCommonFieldsResponse as ServiceNowGetFieldsResponse } from './builtin_action_types/servicenow/types'; @@ -59,6 +60,7 @@ export interface ActionTypeExecutorOptions { secrets: Secrets; params: Params; isEphemeral?: boolean; + taskInfo?: TaskInfo; } export interface ActionResult { diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index dd43606cc79b7..d9383306e1dc6 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -44,6 +44,7 @@ const enabledActionTypes = [ 'test.noop', 'test.delayed', 'test.rate-limit', + 'test.no-attempts-rate-limit', 'test.throw', ]; diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/action_types.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/action_types.ts index a848207bf1b70..e7e48a0938084 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/action_types.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/alerts/server/action_types.ts @@ -37,6 +37,7 @@ export function defineActionTypes( actions.registerType(getDelayedActionType()); actions.registerType(getFailingActionType()); actions.registerType(getRateLimitedActionType()); + actions.registerType(getNoAttemptsRateLimitedActionType()); actions.registerType(getAuthorizationActionType(core)); } @@ -183,6 +184,42 @@ function getRateLimitedActionType() { return result; } +function getNoAttemptsRateLimitedActionType() { + const paramsSchema = schema.object({ + index: schema.string(), + reference: schema.string(), + retryAt: schema.number(), + }); + type ParamsType = TypeOf; + const result: ActionType<{}, {}, ParamsType> = { + id: 'test.no-attempts-rate-limit', + name: 'Test: Rate Limit', + minimumLicenseRequired: 'gold', + maxAttempts: 0, + validate: { + params: paramsSchema, + }, + async executor({ config, params, services }) { + await services.scopedClusterClient.index({ + index: params.index, + refresh: 'wait_for', + body: { + params, + config, + reference: params.reference, + source: 'action:test.rate-limit', + }, + }); + return { + status: 'error', + retry: new Date(params.retryAt), + actionId: '', + }; + }, + }; + return result; +} + function getAuthorizationActionType(core: CoreSetup) { const paramsSchema = schema.object({ callClusterAuthorizationIndex: schema.string(), diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts index f937e63840937..533570ae4c16d 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts @@ -97,21 +97,8 @@ export default function ({ getService }: FtrProviderContext) { }, }) .expect(204); - await esTestIndexTool.waitForDocs('action:test.failing', reference, 1); - await supertest - .put( - `${getUrlPrefix( - Spaces.space1.id - )}/api/alerts_fixture/Actions-cleanup_failed_action_executions/reschedule_task` - ) - .set('kbn-xsrf', 'foo') - .send({ - runAt: new Date().toISOString(), - }) - .expect(200); - await retry.try(async () => { const searchResult = await es.search({ index: '.kibana_task_manager', @@ -139,5 +126,81 @@ export default function ({ getService }: FtrProviderContext) { expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(0); }); }); + + it('should never leaved a failed task, even if max attempts is reached', async () => { + // We have to provide the test.rate-limit the next runAt, for testing purposes + const retryDate = new Date(Date.now() + 1); + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'My action', + connector_type_id: 'test.no-attempts-rate-limit', + config: {}, + secrets: {}, + }) + .expect(200); + objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions'); + + const reference = `actions-enqueue-2:${Spaces.space1.id}:${createdAction.id}`; + await supertest + .post( + `${getUrlPrefix(Spaces.space1.id)}/api/alerts_fixture/${createdAction.id}/enqueue_action` + ) + .set('kbn-xsrf', 'foo') + .send({ + params: { + reference, + index: ES_TEST_INDEX_NAME, + retryAt: retryDate.getTime(), + }, + }) + .expect(204); + + await retry.try(async () => { + const runningSearchResult = await es.search({ + index: '.kibana_task_manager', + body: { + query: { + bool: { + must: [ + { + term: { + 'task.taskType': 'actions:test.no-attempts-rate-limit', + }, + }, + { + term: { + 'task.status': 'running', + }, + }, + ], + }, + }, + }, + }); + expect((runningSearchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(1); + }); + + await retry.try(async () => { + const searchResult = await es.search({ + index: '.kibana_task_manager', + body: { + query: { + bool: { + must: [ + { + term: { + 'task.taskType': 'actions:test.no-attempts-rate-limit', + }, + }, + ], + }, + }, + }, + }); + expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(0); + }); + }); }); } From 6e9b1b57b83f3fddb892eb83a6e4941aff18e11c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Thu, 9 Sep 2021 12:55:28 -0400 Subject: [PATCH 14/32] [APM] Consistent "no data" screen with other Observability solutions (#111630) * logic to show no data screen * fixing i18n * fixing ts * addressing pr comments --- .../public/application/application.test.tsx | 16 +++++- .../app/service_inventory/index.tsx | 13 +---- .../no_services_message.test.tsx | 10 +--- .../service_inventory/no_services_message.tsx | 57 +++---------------- .../service_inventory.test.tsx | 22 ------- .../routing/templates/apm_main_template.tsx | 15 +++++ .../routing/templates/no_data_config.ts | 44 ++++++++++++++ .../templates/settings_template.test.tsx | 16 +++++- .../create_static_index_pattern.test.ts | 2 +- .../create_static_index_pattern.ts | 2 +- .../server/lib/services/get_services/index.ts | 8 --- .../apm/server/lib/services/queries.test.ts | 2 +- .../get_global_apm_server_route_repository.ts | 4 +- .../has_historical_agent_data.ts | 4 +- .../server/routes/historical_data/index.ts | 25 ++++++++ .../shared/page_template/page_template.tsx | 20 +++++-- .../translations/translations/ja-JP.json | 4 -- .../translations/translations/zh-CN.json | 4 -- .../tests/historical_data/has_data.ts | 41 +++++++++++++ .../test/apm_api_integration/tests/index.ts | 4 ++ .../tests/services/top_services.ts | 5 -- 21 files changed, 194 insertions(+), 124 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/routing/templates/no_data_config.ts rename x-pack/plugins/apm/server/{lib/services/get_services => routes/historical_data}/has_historical_agent_data.ts (86%) create mode 100644 x-pack/plugins/apm/server/routes/historical_data/index.ts create mode 100644 x-pack/test/apm_api_integration/tests/historical_data/has_data.ts diff --git a/x-pack/plugins/apm/public/application/application.test.tsx b/x-pack/plugins/apm/public/application/application.test.tsx index cbc72f918877c..144da47828bf7 100644 --- a/x-pack/plugins/apm/public/application/application.test.tsx +++ b/x-pack/plugins/apm/public/application/application.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { act } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import { Observable } from 'rxjs'; -import { CoreStart } from 'src/core/public'; +import { CoreStart, DocLinksStart, HttpStart } from 'src/core/public'; import { mockApmPluginContextValue } from '../context/apm_plugin/mock_apm_plugin_context'; import { createCallApmApi } from '../services/rest/createCallApmApi'; import { renderApp } from './'; @@ -85,6 +85,20 @@ describe('renderApp', () => { getEditAlertFlyout: jest.fn(), }, usageCollection: { reportUiCounter: () => {} }, + http: { + basePath: { + prepend: (path: string) => `/basepath${path}`, + get: () => `/basepath`, + }, + } as HttpStart, + docLinks: ({ + DOC_LINK_VERSION: '0', + ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', + links: { + apm: {}, + observability: { guide: '' }, + }, + } as unknown) as DocLinksStart, } as unknown) as ApmPluginStartDeps; jest.spyOn(window, 'scrollTo').mockReturnValueOnce(undefined); diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx index c72c0cfbbceed..2cdb808622854 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx @@ -179,8 +179,6 @@ export function ServiceInventory() { canCreateJob && !userHasDismissedCallout; - const isLoading = mainStatisticsStatus === FETCH_STATUS.LOADING; - return ( <> @@ -192,17 +190,10 @@ export function ServiceInventory() { )} - ) - } + noItemsMessage={} /> diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.test.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.test.tsx index 3e07e18f95a02..3a3ddcc558679 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.test.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.test.tsx @@ -22,13 +22,9 @@ describe('NoServicesMessage', () => { describe(`when historicalDataFound is ${historicalDataFound}`, () => { it('renders', () => { expect(() => - render( - , - { wrapper: Wrapper } - ) + render(, { + wrapper: Wrapper, + }) ).not.toThrowError(); }); }); diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx index a2dc5feec44f8..872359262cf02 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/no_services_message.tsx @@ -5,76 +5,35 @@ * 2.0. */ -import { EuiEmptyPrompt, EuiLink } from '@elastic/eui'; +import { EuiEmptyPrompt } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { ErrorStatePrompt } from '../../shared/ErrorStatePrompt'; -import { useUpgradeAssistantHref } from '../../shared/Links/kibana'; -import { SetupInstructionsLink } from '../../shared/Links/SetupInstructionsLink'; interface Props { - // any data submitted from APM agents found (not just in the given time range) - historicalDataFound: boolean; status: FETCH_STATUS | undefined; } -export function NoServicesMessage({ historicalDataFound, status }: Props) { - const upgradeAssistantHref = useUpgradeAssistantHref(); - - if (status === 'failure') { - return ; +export function NoServicesMessage({ status }: Props) { + if (status === FETCH_STATUS.LOADING) { + return null; } - if (historicalDataFound) { - return ( - - {i18n.translate('xpack.apm.servicesTable.notFoundLabel', { - defaultMessage: 'No services found', - })} - - } - titleSize="s" - /> - ); + if (status === FETCH_STATUS.FAILURE) { + return ; } return ( - {i18n.translate('xpack.apm.servicesTable.noServicesLabel', { - defaultMessage: `Looks like you don't have any APM services installed. Let's add some!`, + {i18n.translate('xpack.apm.servicesTable.notFoundLabel', { + defaultMessage: 'No services found', })} } titleSize="s" - body={ - -

- {i18n.translate('xpack.apm.servicesTable.7xUpgradeServerMessage', { - defaultMessage: `Upgrading from a pre-7.x version? Make sure you've also upgraded - your APM Server instance(s) to at least 7.0.`, - })} -

-

- {i18n.translate('xpack.apm.servicesTable.7xOldDataMessage', { - defaultMessage: - 'You may also have old data that needs to be migrated.', - })}{' '} - - {i18n.translate('xpack.apm.servicesTable.UpgradeAssistantLink', { - defaultMessage: - 'Learn more by visiting the Kibana Upgrade Assistant', - })} - - . -

- - } - actions={} /> ); } diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/service_inventory.test.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/service_inventory.test.tsx index 8f2e921d4bd83..2ff3f2702cb53 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/service_inventory.test.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/service_inventory.test.tsx @@ -134,28 +134,6 @@ describe('ServiceInventory', () => { expect(container.querySelectorAll('.euiTableRow')).toHaveLength(2); }); - it('should render getting started message, when list is empty and no historical data is found', async () => { - httpGet - .mockResolvedValueOnce({ fallbackToTransactions: false }) - .mockResolvedValueOnce({ - hasLegacyData: false, - hasHistoricalData: false, - items: [], - }); - - const { findByText } = render(, { wrapper }); - - // wait for requests to be made - await waitFor(() => expect(httpGet).toHaveBeenCalledTimes(2)); - - // wait for elements to be rendered - const gettingStartedMessage = await findByText( - "Looks like you don't have any APM services installed. Let's add some!" - ); - - expect(gettingStartedMessage).not.toBeEmptyDOMElement(); - }); - it('should render empty message, when list is empty and historical data is found', async () => { httpGet .mockResolvedValueOnce({ fallbackToTransactions: false }) diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx index 2a1ccd00e5a71..f4494f1841ba3 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx @@ -8,8 +8,10 @@ import { EuiPageHeaderProps, EuiPageTemplateProps } from '@elastic/eui'; import React from 'react'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { useFetcher } from '../../../hooks/use_fetcher'; import { ApmPluginStartDeps } from '../../../plugin'; import { ApmEnvironmentFilter } from '../../shared/EnvironmentFilter'; +import { getNoDataConfig } from './no_data_config'; /* * This template contains: @@ -31,12 +33,25 @@ export function ApmMainTemplate({ children: React.ReactNode; } & EuiPageTemplateProps) { const { services } = useKibana(); + const { http, docLinks } = services; + const basePath = http?.basePath.get(); const ObservabilityPageTemplate = services.observability.navigation.PageTemplate; + const { data } = useFetcher((callApmApi) => { + return callApmApi({ endpoint: 'GET /api/apm/has_data' }); + }, []); + + const noDataConfig = getNoDataConfig({ + basePath, + docsLink: docLinks!.links.observability.guide, + hasData: data?.hasData, + }); + return ( ], diff --git a/x-pack/plugins/apm/public/components/routing/templates/no_data_config.ts b/x-pack/plugins/apm/public/components/routing/templates/no_data_config.ts new file mode 100644 index 0000000000000..868db57a0efdc --- /dev/null +++ b/x-pack/plugins/apm/public/components/routing/templates/no_data_config.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { KibanaPageTemplateProps } from '../../../../../../../src/plugins/kibana_react/public'; + +export function getNoDataConfig({ + docsLink, + basePath, + hasData, +}: { + docsLink: string; + basePath?: string; + hasData?: boolean; +}): KibanaPageTemplateProps['noDataConfig'] { + // Returns no data config when there is no historical data + if (hasData === false) { + return { + solution: i18n.translate('xpack.apm.noDataConfig.solutionName', { + defaultMessage: 'Observability', + }), + actions: { + beats: { + title: i18n.translate('xpack.apm.noDataConfig.beatsCard.title', { + defaultMessage: 'Add data with APM agents', + }), + description: i18n.translate( + 'xpack.apm.noDataConfig.beatsCard.description', + { + defaultMessage: + 'Use APM agents to collect APM data. We make it easy with agents for many popular languages.', + } + ), + href: basePath + `/app/home#/tutorial/apm`, + }, + }, + docsLink, + }; + } +} diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx index d3efef4c88380..b601eb8ffcb2b 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx @@ -11,7 +11,7 @@ import React, { ReactNode } from 'react'; import { SettingsTemplate } from './settings_template'; import { createMemoryHistory } from 'history'; import { MemoryRouter, RouteComponentProps } from 'react-router-dom'; -import { CoreStart } from 'kibana/public'; +import { CoreStart, DocLinksStart, HttpStart } from 'kibana/public'; import { createKibanaReactContext } from 'src/plugins/kibana_react/public'; const { location } = createMemoryHistory(); @@ -25,6 +25,20 @@ const KibanaReactContext = createKibanaReactContext({ }, }, }, + http: { + basePath: { + prepend: (path: string) => `/basepath${path}`, + get: () => `/basepath`, + }, + } as HttpStart, + docLinks: ({ + DOC_LINK_VERSION: '0', + ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', + links: { + apm: {}, + observability: { guide: '' }, + }, + } as unknown) as DocLinksStart, } as Partial); function Wrapper({ children }: { children?: ReactNode }) { diff --git a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts index 35f5721eee05c..46596d8ac864a 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts @@ -8,7 +8,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { createStaticIndexPattern } from './create_static_index_pattern'; import { Setup } from '../helpers/setup_request'; -import * as HistoricalAgentData from '../services/get_services/has_historical_agent_data'; +import * as HistoricalAgentData from '../../routes/historical_data/has_historical_agent_data'; import { InternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; import { APMConfig } from '../..'; diff --git a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts index 414414c6bfe65..6fa96de0b9413 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts @@ -8,7 +8,7 @@ import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server'; import { APM_STATIC_INDEX_PATTERN_ID } from '../../../common/index_pattern_constants'; import apmIndexPattern from '../../tutorial/index_pattern.json'; -import { hasHistoricalAgentData } from '../services/get_services/has_historical_agent_data'; +import { hasHistoricalAgentData } from '../../routes/historical_data/has_historical_agent_data'; import { Setup } from '../helpers/setup_request'; import { APMRouteHandlerResources } from '../../routes/typings'; import { InternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client.js'; diff --git a/x-pack/plugins/apm/server/lib/services/get_services/index.ts b/x-pack/plugins/apm/server/lib/services/get_services/index.ts index 61cb4a28586d7..d4b11880b56ab 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/index.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/index.ts @@ -6,12 +6,10 @@ */ import { Logger } from '@kbn/logging'; -import { isEmpty } from 'lodash'; import { withApmSpan } from '../../../utils/with_apm_span'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { getLegacyDataStatus } from './get_legacy_data_status'; import { getServicesItems } from './get_services_items'; -import { hasHistoricalAgentData } from './has_historical_agent_data'; export async function getServices({ environment, @@ -38,14 +36,8 @@ export async function getServices({ getLegacyDataStatus(setup), ]); - const noDataInCurrentTimeRange = isEmpty(items); - const hasHistoricalData = noDataInCurrentTimeRange - ? await hasHistoricalAgentData(setup) - : true; - return { items, - hasHistoricalData, hasLegacyData, }; }); diff --git a/x-pack/plugins/apm/server/lib/services/queries.test.ts b/x-pack/plugins/apm/server/lib/services/queries.test.ts index be5f280477a09..a4a32229cbd44 100644 --- a/x-pack/plugins/apm/server/lib/services/queries.test.ts +++ b/x-pack/plugins/apm/server/lib/services/queries.test.ts @@ -9,7 +9,7 @@ import { getServiceAgent } from './get_service_agent'; import { getServiceTransactionTypes } from './get_service_transaction_types'; import { getServicesItems } from './get_services/get_services_items'; import { getLegacyDataStatus } from './get_services/get_legacy_data_status'; -import { hasHistoricalAgentData } from './get_services/has_historical_agent_data'; +import { hasHistoricalAgentData } from '../../routes/historical_data/has_historical_agent_data'; import { SearchParamsMock, inspectSearchParams, diff --git a/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts b/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts index 941eb796d3ab3..9bc9108da9055 100644 --- a/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts +++ b/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts @@ -33,6 +33,7 @@ import { sourceMapsRouteRepository } from './source_maps'; import { traceRouteRepository } from './traces'; import { transactionRouteRepository } from './transactions'; import { APMRouteHandlerResources } from './typings'; +import { historicalDataRouteRepository } from './historical_data'; const getTypedGlobalApmServerRouteRepository = () => { const repository = createApmServerRouteRepository() @@ -56,7 +57,8 @@ const getTypedGlobalApmServerRouteRepository = () => { .merge(sourceMapsRouteRepository) .merge(apmFleetRouteRepository) .merge(backendsRouteRepository) - .merge(fallbackToTransactionsRouteRepository); + .merge(fallbackToTransactionsRouteRepository) + .merge(historicalDataRouteRepository); return repository; }; diff --git a/x-pack/plugins/apm/server/lib/services/get_services/has_historical_agent_data.ts b/x-pack/plugins/apm/server/routes/historical_data/has_historical_agent_data.ts similarity index 86% rename from x-pack/plugins/apm/server/lib/services/get_services/has_historical_agent_data.ts rename to x-pack/plugins/apm/server/routes/historical_data/has_historical_agent_data.ts index 97b8a8fa5505b..13591b47a8584 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/has_historical_agent_data.ts +++ b/x-pack/plugins/apm/server/routes/historical_data/has_historical_agent_data.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; +import { ProcessorEvent } from '../../../common/processor_event'; +import { Setup } from '../../lib/helpers/setup_request'; // Note: this logic is duplicated in tutorials/apm/envs/on_prem export async function hasHistoricalAgentData(setup: Setup) { diff --git a/x-pack/plugins/apm/server/routes/historical_data/index.ts b/x-pack/plugins/apm/server/routes/historical_data/index.ts new file mode 100644 index 0000000000000..6e574a435bc83 --- /dev/null +++ b/x-pack/plugins/apm/server/routes/historical_data/index.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { setupRequest } from '../../lib/helpers/setup_request'; +import { createApmServerRoute } from '../create_apm_server_route'; +import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; +import { hasHistoricalAgentData } from './has_historical_agent_data'; + +const hasDataRoute = createApmServerRoute({ + endpoint: 'GET /api/apm/has_data', + options: { tags: ['access:apm'] }, + handler: async (resources) => { + const setup = await setupRequest(resources); + const hasData = await hasHistoricalAgentData(setup); + return { hasData }; + }, +}); + +export const historicalDataRouteRepository = createApmServerRouteRepository().add( + hasDataRoute +); diff --git a/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx b/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx index 965e5dba6a80e..36b69782a424e 100644 --- a/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx +++ b/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx @@ -31,7 +31,10 @@ export type WrappedPageTemplateProps = Pick< | 'restrictWidth' | 'template' | 'isEmptyState' ->; + | 'noDataConfig' +> & { + showSolutionNav?: boolean; +}; export interface ObservabilityPageTemplateDependencies { currentAppId$: Observable; @@ -49,6 +52,7 @@ export function ObservabilityPageTemplate({ getUrlForApp, navigateToApp, navigationSections$, + showSolutionNav = true, ...pageTemplateProps }: ObservabilityPageTemplateProps): React.ReactElement | null { const sections = useObservable(navigationSections$, []); @@ -118,11 +122,15 @@ export function ObservabilityPageTemplate({ {children} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c857c98d5b398..aa9ea1a9b5b76 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6895,20 +6895,16 @@ "xpack.apm.serviceProfiling.valueTypeLabel.samples": "サンプル", "xpack.apm.serviceProfiling.valueTypeLabel.unknown": "その他", "xpack.apm.serviceProfiling.valueTypeLabel.wallTime": "Wall", - "xpack.apm.servicesTable.7xOldDataMessage": "また、移行が必要な古いデータがある可能性もあります。", - "xpack.apm.servicesTable.7xUpgradeServerMessage": "バージョン7.xより前からのアップグレードですか?また、\n APM Server インスタンスを7.0以降にアップグレードしていることも確認してください。", "xpack.apm.servicesTable.environmentColumnLabel": "環境", "xpack.apm.servicesTable.healthColumnLabel": "ヘルス", "xpack.apm.servicesTable.latencyAvgColumnLabel": "レイテンシ(平均)", "xpack.apm.servicesTable.metricsExplanationLabel": "これらのメトリックは何か。", "xpack.apm.servicesTable.nameColumnLabel": "名前", - "xpack.apm.servicesTable.noServicesLabel": "APM サービスがインストールされていないようです。追加しましょう!", "xpack.apm.servicesTable.notFoundLabel": "サービスが見つかりません", "xpack.apm.servicesTable.throughputColumnLabel": "スループット", "xpack.apm.servicesTable.tooltip.metricsExplanation": "サービスメトリックは、トランザクションタイプ「要求」、「ページ読み込み」、または上位の使用可能なトランザクションタイプのいずれかで集計されます。", "xpack.apm.servicesTable.transactionColumnLabel": "トランザクションタイプ", "xpack.apm.servicesTable.transactionErrorRate": "失敗したトランザクション率", - "xpack.apm.servicesTable.UpgradeAssistantLink": "Kibana アップグレードアシスタントで詳細をご覧ください", "xpack.apm.settings.agentConfig": "エージェントの編集", "xpack.apm.settings.agentConfig.createConfigButton.tooltip": "エージェント構成を作成する権限がありません", "xpack.apm.settings.agentConfig.descriptionText": "APMアプリ内からエージェント構成を微調整してください。変更はAPMエージェントに自動的に伝達されるので、再デプロイする必要はありません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2d30e0dcbbd8c..24f1d07049840 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6949,21 +6949,17 @@ "xpack.apm.serviceProfiling.valueTypeLabel.samples": "样例", "xpack.apm.serviceProfiling.valueTypeLabel.unknown": "其他", "xpack.apm.serviceProfiling.valueTypeLabel.wallTime": "现实时间", - "xpack.apm.servicesTable.7xOldDataMessage": "可能还有需要迁移的旧数据。", - "xpack.apm.servicesTable.7xUpgradeServerMessage": "从 7.x 之前的版本升级?另外,确保您已将\n APM Server 实例升级到至少 7.0。", "xpack.apm.servicesTable.environmentColumnLabel": "环境", "xpack.apm.servicesTable.environmentCount": "{environmentCount, plural, one {1 个环境} other {# 个环境}}", "xpack.apm.servicesTable.healthColumnLabel": "运行状况", "xpack.apm.servicesTable.latencyAvgColumnLabel": "延迟(平均值)", "xpack.apm.servicesTable.metricsExplanationLabel": "这些指标是什么?", "xpack.apm.servicesTable.nameColumnLabel": "名称", - "xpack.apm.servicesTable.noServicesLabel": "似乎您没有安装任何 APM 服务。让我们添加一些!", "xpack.apm.servicesTable.notFoundLabel": "未找到任何服务", "xpack.apm.servicesTable.throughputColumnLabel": "吞吐量", "xpack.apm.servicesTable.tooltip.metricsExplanation": "服务指标将基于事务类型“request”、“page-load”或排名靠前的可用事务类型进行聚合。", "xpack.apm.servicesTable.transactionColumnLabel": "事务类型", "xpack.apm.servicesTable.transactionErrorRate": "失败事务率", - "xpack.apm.servicesTable.UpgradeAssistantLink": "通过访问 Kibana 升级助手来了解详情", "xpack.apm.settings.agentConfig": "代理配置", "xpack.apm.settings.agentConfig.createConfigButton.tooltip": "您无权创建代理配置", "xpack.apm.settings.agentConfig.descriptionText": "从 APM 应用中微调您的代理配置。更改将自动传播到 APM 代理,因此无需重新部署。", diff --git a/x-pack/test/apm_api_integration/tests/historical_data/has_data.ts b/x-pack/test/apm_api_integration/tests/historical_data/has_data.ts new file mode 100644 index 0000000000000..ec3f0e5e7f362 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/historical_data/has_data.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const archiveName = 'apm_8.0.0'; + + registry.when( + 'Historical data when data is not loaded', + { config: 'basic', archives: [] }, + () => { + it('handles the empty state', async () => { + const response = await supertest.get(`/api/apm/has_data`); + + expect(response.status).to.be(200); + expect(response.body.hasData).to.be(false); + }); + } + ); + + registry.when( + 'Historical data when data is loaded', + { config: 'basic', archives: [archiveName] }, + () => { + it('returns hasData: true', async () => { + const response = await supertest.get(`/api/apm/has_data`); + + expect(response.status).to.be(200); + expect(response.body.hasData).to.be(true); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts index c0690fd2f8260..6c989e61bc6bf 100644 --- a/x-pack/test/apm_api_integration/tests/index.ts +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -224,6 +224,10 @@ export default function apmApiIntegrationTests(providerContext: FtrProviderConte loadTestFile(require.resolve('./csm/web_core_vitals')); }); + describe('historical_data/has_data', function () { + loadTestFile(require.resolve('./historical_data/has_data')); + }); + registry.run(providerContext); }); } diff --git a/x-pack/test/apm_api_integration/tests/services/top_services.ts b/x-pack/test/apm_api_integration/tests/services/top_services.ts index 23b2ca7cfefe9..8e79d6cda58e1 100644 --- a/x-pack/test/apm_api_integration/tests/services/top_services.ts +++ b/x-pack/test/apm_api_integration/tests/services/top_services.ts @@ -37,7 +37,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(response.status).to.be(200); - expect(response.body.hasHistoricalData).to.be(false); expect(response.body.hasLegacyData).to.be(false); expect(response.body.items.length).to.be(0); }); @@ -66,10 +65,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.eql(200); }); - it('returns hasHistoricalData: true', () => { - expect(response.body.hasHistoricalData).to.be(true); - }); - it('returns hasLegacyData: false', () => { expect(response.body.hasLegacyData).to.be(false); }); From c51c92cd7a3e8748d55fb6d17f8d551ba3c754f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Thu, 9 Sep 2021 12:57:29 -0400 Subject: [PATCH 15/32] [APM] Fix bucket size in alert previews (#111304) * fixing preview charts * using metrics * fixing ts issues * refactoring * refactoring useServiceTransactionTypesFetcher * addressing pr comments * addressing pr comments * addressing pr comments --- .../error_count_alert_trigger/index.tsx | 12 ++- .../apm/public/components/alerting/helper.ts | 26 ++++-- .../index.tsx | 20 +++-- .../index.tsx | 8 +- .../index.tsx | 21 +++-- .../apm_service/apm_service_context.tsx | 6 +- .../use_service_transaction_types_fetcher.tsx | 18 ++-- .../chart_preview/get_transaction_duration.ts | 45 +++++++--- .../get_transaction_error_count.ts | 11 +-- .../get_transaction_error_rate.ts | 85 +++++++++++-------- .../apm/server/routes/alerts/chart_preview.ts | 3 + .../tests/alerts/chart_preview.ts | 1 + 12 files changed, 170 insertions(+), 86 deletions(-) diff --git a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx index a06520f1c5bfc..3103be6c03379 100644 --- a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/index.tsx @@ -15,7 +15,7 @@ import { useEnvironmentsFetcher } from '../../../hooks/use_environments_fetcher' import { useFetcher } from '../../../hooks/use_fetcher'; import { ChartPreview } from '../chart_preview'; import { EnvironmentField, IsAboveField, ServiceField } from '../fields'; -import { AlertMetadata, getAbsoluteTimeRange } from '../helper'; +import { AlertMetadata, getIntervalAndTimeRange, TimeUnit } from '../helper'; import { ServiceAlertTrigger } from '../service_alert_trigger'; export interface AlertParams { @@ -54,14 +54,20 @@ export function ErrorCountAlertTrigger(props: Props) { const { data } = useFetcher( (callApmApi) => { - if (params.windowSize && params.windowUnit) { + const { interval, start, end } = getIntervalAndTimeRange({ + windowSize: params.windowSize, + windowUnit: params.windowUnit as TimeUnit, + }); + if (interval && start && end) { return callApmApi({ endpoint: 'GET /api/apm/alerts/chart_preview/transaction_error_count', params: { query: { - ...getAbsoluteTimeRange(params.windowSize, params.windowUnit), environment: params.environment, serviceName: params.serviceName, + interval, + start, + end, }, }, }); diff --git a/x-pack/plugins/apm/public/components/alerting/helper.ts b/x-pack/plugins/apm/public/components/alerting/helper.ts index 7a8f128e41564..4032c33fa30b7 100644 --- a/x-pack/plugins/apm/public/components/alerting/helper.ts +++ b/x-pack/plugins/apm/public/components/alerting/helper.ts @@ -4,8 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import datemath from '@elastic/datemath'; +import moment from 'moment'; export interface AlertMetadata { environment: string; @@ -15,12 +14,25 @@ export interface AlertMetadata { end?: string; } -export function getAbsoluteTimeRange(windowSize: number, windowUnit: string) { - const now = new Date().toISOString(); +export type TimeUnit = 's' | 'm' | 'h' | 'd'; + +const BUCKET_SIZE = 20; + +export function getIntervalAndTimeRange({ + windowSize, + windowUnit, +}: { + windowSize: number; + windowUnit: TimeUnit; +}) { + const end = Date.now(); + const start = + end - + moment.duration(windowSize, windowUnit).asMilliseconds() * BUCKET_SIZE; return { - start: - datemath.parse(`now-${windowSize}${windowUnit}`)?.toISOString() ?? now, - end: now, + interval: `${windowSize}${windowUnit}`, + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), }; } diff --git a/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx index 2a73cba0a63d5..ba32561ac3378 100644 --- a/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx @@ -29,7 +29,7 @@ import { ServiceField, TransactionTypeField, } from '../fields'; -import { AlertMetadata, getAbsoluteTimeRange } from '../helper'; +import { AlertMetadata, getIntervalAndTimeRange, TimeUnit } from '../helper'; import { ServiceAlertTrigger } from '../service_alert_trigger'; import { PopoverExpression } from '../service_alert_trigger/popover_expression'; @@ -77,9 +77,11 @@ export function TransactionDurationAlertTrigger(props: Props) { createCallApmApi(services as CoreStart); - const transactionTypes = useServiceTransactionTypesFetcher( - metadata?.serviceName - ); + const transactionTypes = useServiceTransactionTypesFetcher({ + serviceName: metadata?.serviceName, + start: metadata?.start, + end: metadata?.end, + }); const params = defaults( { @@ -104,16 +106,22 @@ export function TransactionDurationAlertTrigger(props: Props) { const { data } = useFetcher( (callApmApi) => { - if (params.windowSize && params.windowUnit) { + const { interval, start, end } = getIntervalAndTimeRange({ + windowSize: params.windowSize, + windowUnit: params.windowUnit as TimeUnit, + }); + if (interval && start && end) { return callApmApi({ endpoint: 'GET /api/apm/alerts/chart_preview/transaction_duration', params: { query: { - ...getAbsoluteTimeRange(params.windowSize, params.windowUnit), aggregationType: params.aggregationType, environment: params.environment, serviceName: params.serviceName, transactionType: params.transactionType, + interval, + start, + end, }, }, }); diff --git a/x-pack/plugins/apm/public/components/alerting/transaction_duration_anomaly_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/transaction_duration_anomaly_alert_trigger/index.tsx index 519b18cd3a6b6..f72126284395c 100644 --- a/x-pack/plugins/apm/public/components/alerting/transaction_duration_anomaly_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/transaction_duration_anomaly_alert_trigger/index.tsx @@ -48,9 +48,11 @@ interface Props { export function TransactionDurationAnomalyAlertTrigger(props: Props) { const { alertParams, metadata, setAlertParams, setAlertProperty } = props; - const transactionTypes = useServiceTransactionTypesFetcher( - metadata?.serviceName - ); + const transactionTypes = useServiceTransactionTypesFetcher({ + serviceName: metadata?.serviceName, + start: metadata?.start, + end: metadata?.end, + }); const params = defaults( { diff --git a/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx index 8f2e212a22681..cdbdd4eb4bacb 100644 --- a/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx @@ -23,7 +23,7 @@ import { ServiceField, TransactionTypeField, } from '../fields'; -import { AlertMetadata, getAbsoluteTimeRange } from '../helper'; +import { AlertMetadata, getIntervalAndTimeRange, TimeUnit } from '../helper'; import { ServiceAlertTrigger } from '../service_alert_trigger'; interface AlertParams { @@ -47,10 +47,11 @@ export function TransactionErrorRateAlertTrigger(props: Props) { const { alertParams, metadata, setAlertParams, setAlertProperty } = props; createCallApmApi(services as CoreStart); - - const transactionTypes = useServiceTransactionTypesFetcher( - metadata?.serviceName - ); + const transactionTypes = useServiceTransactionTypesFetcher({ + serviceName: metadata?.serviceName, + start: metadata?.start, + end: metadata?.end, + }); const params = defaults( { ...omit(metadata, ['start', 'end']), ...alertParams }, @@ -72,15 +73,21 @@ export function TransactionErrorRateAlertTrigger(props: Props) { const { data } = useFetcher( (callApmApi) => { - if (params.windowSize && params.windowUnit) { + const { interval, start, end } = getIntervalAndTimeRange({ + windowSize: params.windowSize, + windowUnit: params.windowUnit as TimeUnit, + }); + if (interval && start && end) { return callApmApi({ endpoint: 'GET /api/apm/alerts/chart_preview/transaction_error_rate', params: { query: { - ...getAbsoluteTimeRange(params.windowSize, params.windowUnit), environment: params.environment, serviceName: params.serviceName, transactionType: params.transactionType, + interval, + start, + end, }, }, }); diff --git a/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx b/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx index 6b423cac88887..d6b052a5dc884 100644 --- a/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx +++ b/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx @@ -51,7 +51,11 @@ export function ApmServiceContextProvider({ end, }); - const transactionTypes = useServiceTransactionTypesFetcher(serviceName); + const transactionTypes = useServiceTransactionTypesFetcher({ + serviceName, + start, + end, + }); const transactionType = getTransactionType({ transactionType: query.transactionType, diff --git a/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx b/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx index ab1a2877cf5bf..c2e81cb0c92ae 100644 --- a/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx +++ b/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx @@ -5,19 +5,19 @@ * 2.0. */ -import { useApmParams } from '../../hooks/use_apm_params'; import { useFetcher } from '../../hooks/use_fetcher'; -import { useTimeRange } from '../../hooks/use_time_range'; const INITIAL_DATA = { transactionTypes: [] }; -export function useServiceTransactionTypesFetcher(serviceName?: string) { - const { - query: { rangeFrom, rangeTo }, - } = useApmParams('/services/{serviceName}'); - - const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - +export function useServiceTransactionTypesFetcher({ + serviceName, + start, + end, +}: { + serviceName?: string; + start?: string; + end?: string; +}) { const { data = INITIAL_DATA } = useFetcher( (callApmApi) => { if (serviceName && start && end) { diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts index 3a67076201efa..8e3a44d780630 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts +++ b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts @@ -6,17 +6,19 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { rangeQuery } from '../../../../../observability/server'; import { - PROCESSOR_EVENT, SERVICE_NAME, - TRANSACTION_DURATION, TRANSACTION_TYPE, } from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { AlertParams } from '../../../routes/alerts/chart_preview'; -import { getBucketSize } from '../../helpers/get_bucket_size'; +import { + getDocumentTypeFilterForAggregatedTransactions, + getProcessorEventForAggregatedTransactions, + getSearchAggregatedTransactions, + getTransactionDurationFieldForAggregatedTransactions, +} from '../../helpers/aggregated_transactions'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; export async function getTransactionDurationChartPreview({ @@ -26,43 +28,58 @@ export async function getTransactionDurationChartPreview({ alertParams: AlertParams; setup: Setup & SetupTimeRange; }) { + const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + ...setup, + kuery: '', + }); + const { apmEventClient, start, end } = setup; const { aggregationType, environment, serviceName, transactionType, + interval, } = alertParams; const query = { bool: { filter: [ - { term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } }, ...(serviceName ? [{ term: { [SERVICE_NAME]: serviceName } }] : []), ...(transactionType ? [{ term: { [TRANSACTION_TYPE]: transactionType } }] : []), ...rangeQuery(start, end), ...environmentQuery(environment), + ...getDocumentTypeFilterForAggregatedTransactions( + searchAggregatedTransactions + ), ] as QueryDslQueryContainer[], }, }; - const { intervalString } = getBucketSize({ start, end, numBuckets: 20 }); + const transactionDurationField = getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ); const aggs = { timeseries: { date_histogram: { field: '@timestamp', - fixed_interval: intervalString, + fixed_interval: interval, + min_doc_count: 0, + extended_bounds: { + min: start, + max: end, + }, }, aggs: { agg: aggregationType === 'avg' - ? { avg: { field: TRANSACTION_DURATION } } + ? { avg: { field: transactionDurationField } } : { percentiles: { - field: TRANSACTION_DURATION, + field: transactionDurationField, percents: [aggregationType === '95th' ? 95 : 99], }, }, @@ -70,7 +87,13 @@ export async function getTransactionDurationChartPreview({ }, }; const params = { - apm: { events: [ProcessorEvent.transaction] }, + apm: { + events: [ + getProcessorEventForAggregatedTransactions( + searchAggregatedTransactions + ), + ], + }, body: { size: 0, query, aggs }, }; const resp = await apmEventClient.search( diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_count.ts b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_count.ts index 0ead50c709083..d15f82248dec5 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_count.ts +++ b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_count.ts @@ -10,7 +10,6 @@ import { ProcessorEvent } from '../../../../common/processor_event'; import { AlertParams } from '../../../routes/alerts/chart_preview'; import { rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { getBucketSize } from '../../helpers/get_bucket_size'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; export async function getTransactionErrorCountChartPreview({ @@ -21,7 +20,7 @@ export async function getTransactionErrorCountChartPreview({ alertParams: AlertParams; }) { const { apmEventClient, start, end } = setup; - const { serviceName, environment } = alertParams; + const { serviceName, environment, interval } = alertParams; const query = { bool: { @@ -33,13 +32,15 @@ export async function getTransactionErrorCountChartPreview({ }, }; - const { intervalString } = getBucketSize({ start, end, numBuckets: 20 }); - const aggs = { timeseries: { date_histogram: { field: '@timestamp', - fixed_interval: intervalString, + fixed_interval: interval, + extended_bounds: { + min: start, + max: end, + }, }, }, }; diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts index f4d8ffc2749c3..ed4a7a7208eeb 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts @@ -5,16 +5,18 @@ * 2.0. */ +import { rangeQuery } from '../../../../../observability/server'; import { - PROCESSOR_EVENT, SERVICE_NAME, TRANSACTION_TYPE, } from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { AlertParams } from '../../../routes/alerts/chart_preview'; -import { rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { getBucketSize } from '../../helpers/get_bucket_size'; +import { AlertParams } from '../../../routes/alerts/chart_preview'; +import { + getDocumentTypeFilterForAggregatedTransactions, + getProcessorEventForAggregatedTransactions, + getSearchAggregatedTransactions, +} from '../../helpers/aggregated_transactions'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; import { calculateFailedTransactionRate, @@ -28,43 +30,58 @@ export async function getTransactionErrorRateChartPreview({ setup: Setup & SetupTimeRange; alertParams: AlertParams; }) { - const { apmEventClient, start, end } = setup; - const { serviceName, environment, transactionType } = alertParams; + const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + ...setup, + kuery: '', + }); - const query = { - bool: { - filter: [ - { term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } }, - ...(serviceName ? [{ term: { [SERVICE_NAME]: serviceName } }] : []), - ...(transactionType - ? [{ term: { [TRANSACTION_TYPE]: transactionType } }] - : []), - ...rangeQuery(start, end), - ...environmentQuery(environment), - ], - }, - }; + const { apmEventClient, start, end } = setup; + const { serviceName, environment, transactionType, interval } = alertParams; const outcomes = getOutcomeAggregation(); - const { intervalString } = getBucketSize({ start, end, numBuckets: 20 }); - - const aggs = { - outcomes, - timeseries: { - date_histogram: { - field: '@timestamp', - fixed_interval: intervalString, + const params = { + apm: { + events: [ + getProcessorEventForAggregatedTransactions( + searchAggregatedTransactions + ), + ], + }, + body: { + size: 0, + query: { + bool: { + filter: [ + ...(serviceName ? [{ term: { [SERVICE_NAME]: serviceName } }] : []), + ...(transactionType + ? [{ term: { [TRANSACTION_TYPE]: transactionType } }] + : []), + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...getDocumentTypeFilterForAggregatedTransactions( + searchAggregatedTransactions + ), + ], + }, + }, + aggs: { + outcomes, + timeseries: { + date_histogram: { + field: '@timestamp', + fixed_interval: interval, + extended_bounds: { + min: start, + max: end, + }, + }, + aggs: { outcomes }, + }, }, - aggs: { outcomes }, }, }; - const params = { - apm: { events: [ProcessorEvent.transaction] }, - body: { size: 0, query, aggs }, - }; - const resp = await apmEventClient.search( 'get_transaction_error_rate_chart_preview', params diff --git a/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts b/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts index 13879cb5fecb7..c28bca5048350 100644 --- a/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts +++ b/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts @@ -26,6 +26,9 @@ const alertParamsRt = t.intersection([ }), environmentRt, rangeRt, + t.type({ + interval: t.string, + }), ]); export type AlertParams = t.TypeOf; diff --git a/x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts b/x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts index c8bb844238020..d3e5b08233487 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/chart_preview.ts @@ -24,6 +24,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { serviceName: 'opbeans-java', transactionType: 'request' as string | undefined, environment: 'ENVIRONMENT_ALL', + interval: '5m', }, }, }); From c006c82db9325a84cc2ee2c1f50b645377cfe892 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 9 Sep 2021 13:34:40 -0400 Subject: [PATCH 16/32] [Maps] Add force-refresh toggle (#104691) Adds the ability for users to control whether a layer should refresh on auto-update or when the refresh-button is clicked. This is required to display static layers from geo-data indexed in Elasticsearch. --- .../__mocks__/regions_layer.mock.ts | 2 + .../VisitorBreakdownMap/useLayerList.ts | 2 + .../data_request_descriptor_types.ts | 31 ++-- .../common/descriptor_types/map_descriptor.ts | 5 - .../source_descriptor_types.ts | 1 + .../public/actions/data_request_actions.ts | 74 +++++--- .../maps/public/actions/layer_actions.ts | 16 +- .../maps/public/actions/map_actions.test.ts | 3 - .../maps/public/actions/map_actions.ts | 31 ++-- .../layers/__fixtures__/mock_sync_context.ts | 18 +- .../blended_vector_layer.test.tsx | 3 + .../blended_vector_layer.ts | 17 +- .../layers/build_vector_request_meta.ts | 32 ++++ .../create_choropleth_layer_descriptor.ts | 3 + .../create_region_map_layer_descriptor.ts | 1 + .../layers/heatmap_layer/heatmap_layer.ts | 22 ++- .../maps/public/classes/layers/layer.test.ts | 1 + .../create_layer_descriptor.test.ts | 3 + .../observability/create_layer_descriptor.ts | 1 + .../security/create_layer_descriptors.test.ts | 9 + .../tiled_vector_layer/tiled_vector_layer.tsx | 14 +- .../classes/layers/vector_layer/utils.tsx | 20 ++- .../layers/vector_layer/vector_layer.tsx | 67 ++++--- .../vector_tile_layer.test.ts | 4 +- .../es_agg_source/es_agg_source.test.ts | 1 + .../es_geo_grid_source.test.ts | 7 +- .../es_geo_line_source.test.ts | 8 +- .../create_layer_descriptor.test.ts | 1 + .../es_search_source/es_search_source.test.ts | 7 +- .../es_search_source/es_search_source.tsx | 4 +- .../classes/sources/es_source/es_source.ts | 20 ++- .../geojson_file_source/geojson_file.test.ts | 6 +- .../geojson_file_source.ts | 4 +- .../mvt_single_layer_vector_source.tsx | 4 +- .../maps/public/classes/sources/source.ts | 16 +- .../sources/table_source/table_source.test.ts | 8 +- .../sources/table_source/table_source.ts | 13 +- .../sources/vector_source/vector_source.tsx | 12 +- ...p_fetch.test.js => can_skip_fetch.test.ts} | 163 ++++++++++-------- .../public/classes/util/can_skip_fetch.ts | 80 ++++----- .../maps/public/classes/util/data_request.ts | 12 +- .../classes/util/is_refresh_only_query.ts | 24 --- .../classes/util/mb_filter_expressions.ts | 8 +- .../components/force_refresh_checkbox.tsx | 42 +++++ .../components/global_filter_checkbox.tsx | 24 ++- .../components/global_time_checkbox.tsx | 25 ++- .../filter_editor/filter_editor.tsx | 28 ++- .../reducers/map/data_request_utils.test.ts | 18 +- .../public/reducers/map/data_request_utils.ts | 14 +- .../plugins/maps/public/reducers/map/map.ts | 1 - .../plugins/maps/public/reducers/map/types.ts | 5 +- .../routes/map_page/map_app/map_app.tsx | 8 +- .../routes/map_page/saved_map/saved_map.ts | 2 +- .../public/selectors/map_selectors.test.ts | 3 - .../maps/public/selectors/map_selectors.ts | 10 +- 55 files changed, 536 insertions(+), 422 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/layers/build_vector_request_meta.ts rename x-pack/plugins/maps/public/classes/util/{can_skip_fetch.test.js => can_skip_fetch.test.ts} (81%) delete mode 100644 x-pack/plugins/maps/public/classes/util/is_refresh_only_query.ts create mode 100644 x-pack/plugins/maps/public/components/force_refresh_checkbox.tsx diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/__mocks__/regions_layer.mock.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/__mocks__/regions_layer.mock.ts index abc676d17ccfa..94de1c088562a 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/__mocks__/regions_layer.mock.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/__mocks__/regions_layer.mock.ts @@ -11,6 +11,7 @@ export const mockLayerList = [ { leftField: 'iso2', right: { + applyForceRefresh: true, applyGlobalQuery: true, applyGlobalTime: true, type: 'ES_TERM_SOURCE', @@ -86,6 +87,7 @@ export const mockLayerList = [ { leftField: 'region_iso_code', right: { + applyForceRefresh: true, applyGlobalQuery: true, applyGlobalTime: true, type: 'ES_TERM_SOURCE', diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/useLayerList.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/useLayerList.ts index c998964b86400..f96595ad7043a 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/useLayerList.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/useLayerList.ts @@ -45,6 +45,7 @@ const ES_TERM_SOURCE_COUNTRY: ESTermSourceDescriptor = { indexPatternId: APM_STATIC_INDEX_PATTERN_ID, applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, }; const ES_TERM_SOURCE_REGION: ESTermSourceDescriptor = { @@ -60,6 +61,7 @@ const ES_TERM_SOURCE_REGION: ESTermSourceDescriptor = { indexPatternId: APM_STATIC_INDEX_PATTERN_ID, applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, }; const getWhereQuery = (serviceName: string) => { diff --git a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts index 8e996934ef69e..f2c13a81045ee 100644 --- a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts @@ -7,10 +7,10 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import { Query } from 'src/plugins/data/public'; +import type { Query } from 'src/plugins/data/common'; import { SortDirection } from 'src/plugins/data/common/search'; import { RENDER_AS, SCALING_TYPES } from '../constants'; -import { MapExtent, MapQuery } from './map_descriptor'; +import { MapExtent } from './map_descriptor'; import { Filter, TimeRange } from '../../../../../src/plugins/data/common'; import { ESTermSourceDescriptor } from './source_descriptor_types'; @@ -20,12 +20,11 @@ export type Timeslice = { }; // Global map state passed to every layer. -export type MapFilters = { +export type DataFilters = { buffer?: MapExtent; // extent with additional buffer extent?: MapExtent; // map viewport filters: Filter[]; - query?: MapQuery; - refreshTimerLastTriggeredAt?: string; + query?: Query; searchSessionId?: string; timeFilters: TimeRange; timeslice?: Timeslice; @@ -60,24 +59,24 @@ export type VectorSourceSyncMeta = | ESTermSourceSyncMeta | null; -export type VectorSourceRequestMeta = MapFilters & { +export type VectorSourceRequestMeta = DataFilters & { applyGlobalQuery: boolean; applyGlobalTime: boolean; + applyForceRefresh: boolean; fieldNames: string[]; geogridPrecision?: number; - timesiceMaskField?: string; - sourceQuery?: MapQuery; + timesliceMaskField?: string; + sourceQuery?: Query; sourceMeta: VectorSourceSyncMeta; + isForceRefresh: boolean; }; -export type VectorJoinSourceRequestMeta = Omit & { - sourceQuery?: Query; -}; +export type VectorJoinSourceRequestMeta = Omit; -export type VectorStyleRequestMeta = MapFilters & { +export type VectorStyleRequestMeta = DataFilters & { dynamicStyleFields: string[]; isTimeAware: boolean; - sourceQuery: MapQuery; + sourceQuery: Query; timeFilters: TimeRange; }; @@ -107,7 +106,7 @@ export type VectorTileLayerMeta = { }; // Partial because objects are justified downstream in constructors -export type DataMeta = Partial< +export type DataRequestMeta = Partial< VectorSourceRequestMeta & VectorJoinSourceRequestMeta & VectorStyleRequestMeta & @@ -134,8 +133,8 @@ export type StyleMetaData = { export type DataRequestDescriptor = { dataId: string; - dataMetaAtStart?: DataMeta | null; + dataRequestMetaAtStart?: DataRequestMeta | null; dataRequestToken?: symbol; data?: object; - dataMeta?: DataMeta; + dataRequestMeta?: DataRequestMeta; }; diff --git a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts index 20d811fab62f7..8cb43713face4 100644 --- a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts +++ b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts @@ -10,7 +10,6 @@ import { ReactNode } from 'react'; import { GeoJsonProperties } from 'geojson'; import { Geometry } from 'geojson'; -import { Query } from '../../../../../src/plugins/data/common'; import { DRAW_SHAPE, ES_SPATIAL_RELATIONS } from '../constants'; export type MapExtent = { @@ -20,10 +19,6 @@ export type MapExtent = { maxLat: number; }; -export type MapQuery = Query & { - queryLastTriggeredAt?: string; -}; - export type MapCenter = { lat: number; lon: number; diff --git a/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts index 9a2af711ea2c7..285c4043e46c7 100644 --- a/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts @@ -42,6 +42,7 @@ export type AbstractESSourceDescriptor = AbstractSourceDescriptor & { geoField?: string; applyGlobalQuery: boolean; applyGlobalTime: boolean; + applyForceRefresh: boolean; }; type AbstractAggDescriptor = { diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index 50df95a52c4d4..48b0a416b5f0f 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -45,22 +45,28 @@ import { } from './map_action_constants'; import { ILayer } from '../classes/layers/layer'; import { IVectorLayer } from '../classes/layers/vector_layer'; -import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types'; +import { DataRequestMeta, MapExtent, DataFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util'; const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; export type DataRequestContext = { - startLoading(dataId: string, requestToken: symbol, requestMeta?: DataMeta): void; - stopLoading(dataId: string, requestToken: symbol, data: object, resultsMeta?: DataMeta): void; + startLoading(dataId: string, requestToken: symbol, requestMeta?: DataRequestMeta): void; + stopLoading( + dataId: string, + requestToken: symbol, + data: object, + resultsMeta?: DataRequestMeta + ): void; onLoadError(dataId: string, requestToken: symbol, errorMessage: string): void; onJoinError(errorMessage: string): void; updateSourceData(newData: unknown): void; isRequestStillActive(dataId: string, requestToken: symbol): boolean; registerCancelCallback(requestToken: symbol, callback: () => void): void; - dataFilters: MapFilters; - forceRefresh: boolean; + dataFilters: DataFilters; + forceRefreshDueToDrawing: boolean; // Boolean signaling data request triggered by a user updating layer features via drawing tools. When true, layer will re-load regardless of "source.applyForceRefresh" flag. + isForceRefresh: boolean; // Boolean signaling data request triggered by auto-refresh timer or user clicking refresh button. When true, layer will re-load only when "source.applyForceRefresh" flag is set to true. }; export function clearDataRequests(layer: ILayer) { @@ -112,13 +118,14 @@ function getDataRequestContext( dispatch: ThunkDispatch, getState: () => MapStoreState, layerId: string, - forceRefresh: boolean = false + forceRefreshDueToDrawing: boolean, + isForceRefresh: boolean ): DataRequestContext { return { dataFilters: getDataFilters(getState()), - startLoading: (dataId: string, requestToken: symbol, meta: DataMeta) => + startLoading: (dataId: string, requestToken: symbol, meta: DataRequestMeta) => dispatch(startDataLoad(layerId, dataId, requestToken, meta)), - stopLoading: (dataId: string, requestToken: symbol, data: object, meta: DataMeta) => + stopLoading: (dataId: string, requestToken: symbol, data: object, meta: DataRequestMeta) => dispatch(endDataLoad(layerId, dataId, requestToken, data, meta)), onLoadError: (dataId: string, requestToken: symbol, errorMessage: string) => dispatch(onDataLoadError(layerId, dataId, requestToken, errorMessage)), @@ -136,17 +143,18 @@ function getDataRequestContext( }, registerCancelCallback: (requestToken: symbol, callback: () => void) => dispatch(registerCancelCallback(requestToken, callback)), - forceRefresh, + forceRefreshDueToDrawing, + isForceRefresh, }; } -export function syncDataForAllLayers() { +export function syncDataForAllLayers(isForceRefresh: boolean) { return async ( dispatch: ThunkDispatch, getState: () => MapStoreState ) => { const syncPromises = getLayerList(getState()).map((layer) => { - return dispatch(syncDataForLayer(layer)); + return dispatch(syncDataForLayer(layer, isForceRefresh)); }); await Promise.all(syncPromises); }; @@ -162,19 +170,20 @@ function syncDataForAllJoinLayers() { return 'hasJoins' in layer ? (layer as IVectorLayer).hasJoins() : false; }) .map((layer) => { - return dispatch(syncDataForLayer(layer)); + return dispatch(syncDataForLayer(layer, false)); }); await Promise.all(syncPromises); }; } -export function syncDataForLayer(layer: ILayer, forceRefresh: boolean = false) { +export function syncDataForLayerDueToDrawing(layer: ILayer) { return async (dispatch: Dispatch, getState: () => MapStoreState) => { const dataRequestContext = getDataRequestContext( dispatch, getState, layer.getId(), - forceRefresh + true, + false ); if (!layer.isVisible() || !layer.showAtZoomLevel(dataRequestContext.dataFilters.zoom)) { return; @@ -183,14 +192,30 @@ export function syncDataForLayer(layer: ILayer, forceRefresh: boolean = false) { }; } -export function syncDataForLayerId(layerId: string | null) { +export function syncDataForLayer(layer: ILayer, isForceRefresh: boolean) { + return async (dispatch: Dispatch, getState: () => MapStoreState) => { + const dataRequestContext = getDataRequestContext( + dispatch, + getState, + layer.getId(), + false, + isForceRefresh + ); + if (!layer.isVisible() || !layer.showAtZoomLevel(dataRequestContext.dataFilters.zoom)) { + return; + } + await layer.syncData(dataRequestContext); + }; +} + +export function syncDataForLayerId(layerId: string | null, isForceRefresh: boolean) { return async ( dispatch: ThunkDispatch, getState: () => MapStoreState ) => { const layer = getLayerById(layerId, getState()); if (layer) { - dispatch(syncDataForLayer(layer)); + dispatch(syncDataForLayer(layer, isForceRefresh)); } }; } @@ -204,7 +229,12 @@ function setLayerDataLoadErrorStatus(layerId: string, errorMessage: string | nul }; } -function startDataLoad(layerId: string, dataId: string, requestToken: symbol, meta: DataMeta) { +function startDataLoad( + layerId: string, + dataId: string, + requestToken: symbol, + meta: DataRequestMeta +) { return ( dispatch: ThunkDispatch, getState: () => MapStoreState @@ -237,7 +267,7 @@ function endDataLoad( dataId: string, requestToken: symbol, data: object, - meta: DataMeta + meta: DataRequestMeta ) { return ( dispatch: ThunkDispatch, @@ -342,7 +372,7 @@ export function fitToLayerExtent(layerId: string) { if (targetLayer) { try { const bounds = await targetLayer.getBounds( - getDataRequestContext(dispatch, getState, layerId) + getDataRequestContext(dispatch, getState, layerId, false, false) ); if (bounds) { await dispatch(setGotoWithBounds(scaleBounds(bounds, FIT_TO_BOUNDS_SCALE_FACTOR))); @@ -374,7 +404,9 @@ export function fitToDataBounds(onNoBounds?: () => void) { if (!(await layer.isFittable())) { return null; } - return layer.getBounds(getDataRequestContext(dispatch, getState, layer.getId())); + return layer.getBounds( + getDataRequestContext(dispatch, getState, layer.getId(), false, false) + ); }); let bounds; @@ -442,7 +474,7 @@ export function autoFitToBounds() { // Ensure layer syncing occurs when setGotoWithBounds is not triggered. function onNoBounds() { if (localSetQueryCallId === lastSetQueryCallId) { - dispatch(syncDataForAllLayers()); + dispatch(syncDataForAllLayers(false)); } } dispatch(fitToDataBounds(onNoBounds)); diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index edd21090143bf..d5bb061ccf430 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -80,7 +80,7 @@ export function rollbackToTrackedLayerStateForSelectedLayer() { // syncDataForLayer may not trigger endDataLoad if no re-fetch is required dispatch(updateStyleMeta(layerId)); - dispatch(syncDataForLayerId(layerId)); + dispatch(syncDataForLayerId(layerId, false)); }; } @@ -149,7 +149,7 @@ export function addLayer(layerDescriptor: LayerDescriptor) { type: ADD_LAYER, layer: layerDescriptor, }); - dispatch(syncDataForLayerId(layerDescriptor.id)); + dispatch(syncDataForLayerId(layerDescriptor.id, false)); const layer = createLayerInstance(layerDescriptor); const features = await layer.getLicensedFeatures(); @@ -226,7 +226,7 @@ export function setLayerVisibility(layerId: string, makeVisible: boolean) { visibility: makeVisible, }); if (makeVisible) { - dispatch(syncDataForLayerId(layerId)); + dispatch(syncDataForLayerId(layerId, false)); } }; } @@ -330,7 +330,7 @@ function updateMetricsProp(layerId: string, value: unknown) { value, }); await dispatch(updateStyleProperties(layerId, previousFields as IESAggField[])); - dispatch(syncDataForLayerId(layerId)); + dispatch(syncDataForLayerId(layerId, false)); }; } @@ -356,7 +356,7 @@ export function updateSourceProp( if (newLayerType) { dispatch(updateLayerType(layerId, newLayerType)); } - dispatch(syncDataForLayerId(layerId)); + dispatch(syncDataForLayerId(layerId, false)); }; } @@ -459,7 +459,7 @@ export function setLayerQuery(id: string, query: Query) { newValue: query, }); - dispatch(syncDataForLayerId(id)); + dispatch(syncDataForLayerId(id, false)); }; } @@ -563,7 +563,7 @@ export function updateLayerStyle(layerId: string, styleDescriptor: StyleDescript dispatch(updateStyleMeta(layerId)); // Style update may require re-fetch, for example ES search may need to retrieve field used for dynamic styling - dispatch(syncDataForLayerId(layerId)); + dispatch(syncDataForLayerId(layerId, false)); }; } @@ -589,7 +589,7 @@ export function setJoinsForLayer(layer: ILayer, joins: JoinDescriptor[]) { joins, }); await dispatch(updateStyleProperties(layer.getId(), previousFields)); - dispatch(syncDataForLayerId(layer.getId())); + dispatch(syncDataForLayerId(layer.getId(), false)); }; } diff --git a/x-pack/plugins/maps/public/actions/map_actions.test.ts b/x-pack/plugins/maps/public/actions/map_actions.test.ts index d222d8e5b0466..935ca332baa22 100644 --- a/x-pack/plugins/maps/public/actions/map_actions.test.ts +++ b/x-pack/plugins/maps/public/actions/map_actions.test.ts @@ -277,7 +277,6 @@ describe('map_actions', () => { const query = { language: 'kuery', query: '', - queryLastTriggeredAt: '2020-08-14T15:07:12.276Z', }; const timeFilters = { from: 'now-1y', to: 'now' }; const filters = [ @@ -327,7 +326,6 @@ describe('map_actions', () => { const newQuery = { language: 'kuery', query: 'foobar', - queryLastTriggeredAt: '2020-08-14T15:07:12.276Z', }; const setQueryAction = await setQuery({ query: newQuery, @@ -384,7 +382,6 @@ describe('map_actions', () => { }); await setQueryAction(dispatchMock, getStoreMock); - // Only checking calls length instead of calls because queryLastTriggeredAt changes on this run expect(dispatchMock.mock.calls.length).toEqual(2); }); }); diff --git a/x-pack/plugins/maps/public/actions/map_actions.ts b/x-pack/plugins/maps/public/actions/map_actions.ts index c1db14347460f..ba52203ce486b 100644 --- a/x-pack/plugins/maps/public/actions/map_actions.ts +++ b/x-pack/plugins/maps/public/actions/map_actions.ts @@ -51,7 +51,11 @@ import { UPDATE_MAP_SETTING, UPDATE_EDIT_STATE, } from './map_action_constants'; -import { autoFitToBounds, syncDataForAllLayers, syncDataForLayer } from './data_request_actions'; +import { + autoFitToBounds, + syncDataForAllLayers, + syncDataForLayerDueToDrawing, +} from './data_request_actions'; import { addLayer, addLayerWithoutDataSync } from './layer_actions'; import { MapSettings } from '../reducers/map'; import { DrawState, MapCenterAndZoom, MapExtent, Timeslice } from '../../common/descriptor_types'; @@ -172,7 +176,7 @@ export function mapExtentChanged(mapExtentState: MapExtentState) { }); } - dispatch(syncDataForAllLayers()); + dispatch(syncDataForAllLayers(false)); }; } @@ -212,10 +216,6 @@ export function clearGoto() { return { type: CLEAR_GOTO }; } -function generateQueryTimestamp() { - return new Date().toISOString(); -} - export function setQuery({ query, timeFilters, @@ -240,11 +240,6 @@ export function setQuery({ getState: () => MapStoreState ) => { const prevQuery = getQuery(getState()); - const prevTriggeredAt = - prevQuery && prevQuery.queryLastTriggeredAt - ? prevQuery.queryLastTriggeredAt - : generateQueryTimestamp(); - const prevTimeFilters = getTimeFilters(getState()); function getNextTimeslice() { @@ -261,11 +256,7 @@ export function setQuery({ const nextQueryContext = { timeFilters: timeFilters ? timeFilters : prevTimeFilters, timeslice: getNextTimeslice(), - query: { - ...(query ? query : prevQuery), - // ensure query changes to trigger re-fetch when "Refresh" clicked - queryLastTriggeredAt: forceRefresh ? generateQueryTimestamp() : prevTriggeredAt, - }, + query: query ? query : prevQuery, filters: filters ? filters : getFilters(getState()), searchSessionId: searchSessionId ? searchSessionId : getSearchSessionId(getState()), searchSessionMapBuffer, @@ -280,7 +271,7 @@ export function setQuery({ searchSessionMapBuffer: getSearchSessionMapBuffer(getState()), }; - if (_.isEqual(nextQueryContext, prevQueryContext)) { + if (!forceRefresh && _.isEqual(nextQueryContext, prevQueryContext)) { // do nothing if query context has not changed return; } @@ -293,7 +284,7 @@ export function setQuery({ if (getMapSettings(getState()).autoFitToDataBounds) { dispatch(autoFitToBounds()); } else { - await dispatch(syncDataForAllLayers()); + await dispatch(syncDataForAllLayers(forceRefresh)); } }; } @@ -372,7 +363,7 @@ export function addNewFeatureToIndex(geometry: Geometry | Position[]) { try { await layer.addFeature(geometry); - await dispatch(syncDataForLayer(layer, true)); + await dispatch(syncDataForLayerDueToDrawing(layer)); } catch (e) { getToasts().addError(e, { title: i18n.translate('xpack.maps.mapActions.addFeatureError', { @@ -399,7 +390,7 @@ export function deleteFeatureFromIndex(featureId: string) { } try { await layer.deleteFeature(featureId); - await dispatch(syncDataForLayer(layer, true)); + await dispatch(syncDataForLayerDueToDrawing(layer)); } catch (e) { getToasts().addError(e, { title: i18n.translate('xpack.maps.mapActions.removeFeatureError', { diff --git a/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts b/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts index 16aca6760c4d5..b81ba6c854629 100644 --- a/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts +++ b/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts @@ -7,21 +7,22 @@ import sinon from 'sinon'; import { DataRequestContext } from '../../../actions'; -import { DataMeta, MapFilters } from '../../../../common/descriptor_types'; +import { DataRequestMeta, DataFilters } from '../../../../common/descriptor_types'; export class MockSyncContext implements DataRequestContext { - dataFilters: MapFilters; + dataFilters: DataFilters; isRequestStillActive: (dataId: string, requestToken: symbol) => boolean; onLoadError: (dataId: string, requestToken: symbol, errorMessage: string) => void; registerCancelCallback: (requestToken: symbol, callback: () => void) => void; - startLoading: (dataId: string, requestToken: symbol, meta: DataMeta) => void; - stopLoading: (dataId: string, requestToken: symbol, data: object, meta: DataMeta) => void; + startLoading: (dataId: string, requestToken: symbol, meta: DataRequestMeta) => void; + stopLoading: (dataId: string, requestToken: symbol, data: object, meta: DataRequestMeta) => void; onJoinError: (errorMessage: string) => void; updateSourceData: (newData: unknown) => void; - forceRefresh: boolean; + forceRefreshDueToDrawing: boolean; + isForceRefresh: boolean; - constructor({ dataFilters }: { dataFilters: Partial }) { - const mapFilters: MapFilters = { + constructor({ dataFilters }: { dataFilters: Partial }) { + const mapFilters: DataFilters = { filters: [], timeFilters: { from: 'now', @@ -41,6 +42,7 @@ export class MockSyncContext implements DataRequestContext { this.stopLoading = sinon.spy(); this.onJoinError = sinon.spy(); this.updateSourceData = sinon.spy(); - this.forceRefresh = false; + this.forceRefreshDueToDrawing = false; + this.isForceRefresh = false; } } diff --git a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.test.tsx b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.test.tsx index 4c81ee67e1daf..d4138ccfaf319 100644 --- a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.test.tsx +++ b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.test.tsx @@ -63,6 +63,7 @@ describe('getSource', () => { ...documentSourceDescriptor, applyGlobalQuery: false, applyGlobalTime: false, + applyForceRefresh: false, }), layerDescriptor: BlendedVectorLayer.createDescriptor( { @@ -86,6 +87,7 @@ describe('getSource', () => { geoField: sourceDescriptor.geoField, applyGlobalQuery: sourceDescriptor.applyGlobalQuery, applyGlobalTime: sourceDescriptor.applyGlobalTime, + applyForceRefresh: sourceDescriptor.applyForceRefresh, }; expect(abstractEsSourceDescriptor).toEqual({ type: sourceDescriptor.type, @@ -94,6 +96,7 @@ describe('getSource', () => { indexPatternId: 'myIndexPattern', applyGlobalQuery: false, applyGlobalTime: false, + applyForceRefresh: false, } as AbstractESSourceDescriptor); }); }); diff --git a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts index 5db22ff5354a8..d2734265f3bc3 100644 --- a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts @@ -60,6 +60,7 @@ function getClusterSource(documentSource: IESSource, documentStyle: IVectorStyle }); clusterSourceDescriptor.applyGlobalQuery = documentSource.getApplyGlobalQuery(); clusterSourceDescriptor.applyGlobalTime = documentSource.getApplyGlobalTime(); + clusterSourceDescriptor.applyForceRefresh = documentSource.getApplyForceRefresh(); clusterSourceDescriptor.metrics = [ { type: AGG_TYPE.COUNT, @@ -290,16 +291,18 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { async syncData(syncContext: DataRequestContext) { const dataRequestId = ACTIVE_COUNT_DATA_ID; const requestToken = Symbol(`layer-active-count:${this.getId()}`); - const searchFilters: VectorSourceRequestMeta = await this._getSearchFilters( + const requestMeta: VectorSourceRequestMeta = await this._getVectorSourceRequestMeta( + syncContext.isForceRefresh, syncContext.dataFilters, this.getSource(), this.getCurrentStyle() ); const source = this.getSource(); - const canSkipFetch = await canSkipSourceUpdate({ + + const canSkipSourceFetch = await canSkipSourceUpdate({ source, prevDataRequest: this.getDataRequest(dataRequestId), - nextMeta: searchFilters, + nextRequestMeta: requestMeta, extentAware: source.isFilterByMapBounds(), getUpdateDueToTimeslice: (timeslice?: Timeslice) => { return this._getUpdateDueToTimesliceFromSourceRequestMeta(source, timeslice); @@ -308,7 +311,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { let activeSource; let activeStyle; - if (canSkipFetch) { + if (canSkipSourceFetch) { // Even when source fetch is skipped, need to call super._syncData to sync StyleMeta and formatters if (this._isClustered) { activeSource = this._clusterSource; @@ -320,12 +323,12 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { } else { let isSyncClustered; try { - syncContext.startLoading(dataRequestId, requestToken, searchFilters); + syncContext.startLoading(dataRequestId, requestToken, requestMeta); isSyncClustered = !(await this._documentSource.canLoadAllDocuments( - searchFilters, + requestMeta, syncContext.registerCancelCallback.bind(null, requestToken) )); - syncContext.stopLoading(dataRequestId, requestToken, { isSyncClustered }, searchFilters); + syncContext.stopLoading(dataRequestId, requestToken, { isSyncClustered }, requestMeta); } catch (error) { if (!(error instanceof DataRequestAbortError) || !isSearchSourceAbortError(error)) { syncContext.onLoadError(dataRequestId, requestToken, error.message); diff --git a/x-pack/plugins/maps/public/classes/layers/build_vector_request_meta.ts b/x-pack/plugins/maps/public/classes/layers/build_vector_request_meta.ts new file mode 100644 index 0000000000000..4d52dacc63782 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/build_vector_request_meta.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import _ from 'lodash'; +import type { Query } from 'src/plugins/data/common'; +import { DataFilters, VectorSourceRequestMeta } from '../../../common/descriptor_types'; +import { IVectorSource } from '../sources/vector_source'; +import { ITermJoinSource } from '../sources/term_join_source'; + +export function buildVectorRequestMeta( + source: IVectorSource | ITermJoinSource, + fieldNames: string[], + dataFilters: DataFilters, + sourceQuery: Query | null | undefined, + isForceRefresh: boolean +): VectorSourceRequestMeta { + return { + ...dataFilters, + fieldNames: _.uniq(fieldNames).sort(), + geogridPrecision: source.getGeoGridPrecision(dataFilters.zoom), + sourceQuery: sourceQuery ? sourceQuery : undefined, + applyGlobalQuery: source.getApplyGlobalQuery(), + applyGlobalTime: source.getApplyGlobalTime(), + sourceMeta: source.getSyncMeta(), + applyForceRefresh: source.isESSource() ? source.getApplyForceRefresh() : false, + isForceRefresh, + }; +} diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts index a4955a965d77c..6b91e4812a1d6 100644 --- a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts @@ -64,6 +64,7 @@ function createChoroplethLayerDescriptor({ metrics: [metricsDescriptor], applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, }, }, ], @@ -148,6 +149,8 @@ export function createEsChoroplethLayerDescriptor({ scalingType: SCALING_TYPES.LIMIT, tooltipProperties: [leftJoinField], applyGlobalQuery: false, + applyGlobalTime: false, + applyForceRefresh: false, }), leftField: leftJoinField, rightIndexPatternId, diff --git a/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts index 229532c09f955..408460de28aeb 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts @@ -92,6 +92,7 @@ export function createRegionMapLayerDescriptor({ metrics: [metricsDescriptor], applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, }; if (termsSize !== undefined) { termSourceDescriptor.size = termsSize; diff --git a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts index d12c8432a4191..d65d114205163 100644 --- a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts @@ -10,11 +10,12 @@ import { FeatureCollection } from 'geojson'; import { AbstractLayer } from '../layer'; import { HeatmapStyle } from '../../styles/heatmap/heatmap_style'; import { EMPTY_FEATURE_COLLECTION, LAYER_TYPE } from '../../../../common/constants'; -import { HeatmapLayerDescriptor, MapQuery } from '../../../../common/descriptor_types'; +import { HeatmapLayerDescriptor } from '../../../../common/descriptor_types'; import { ESGeoGridSource } from '../../sources/es_geo_grid_source'; import { addGeoJsonMbSource, getVectorSourceBounds, syncVectorSource } from '../vector_layer'; import { DataRequestContext } from '../../../actions'; import { DataRequestAbortError } from '../../util/data_request'; +import { buildVectorRequestMeta } from '../build_vector_request_meta'; const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__'; // unique name to store scaled value for weighting @@ -94,21 +95,18 @@ export class HeatmapLayer extends AbstractLayer { return; } - const sourceQuery = this.getQuery() as MapQuery; try { await syncVectorSource({ layerId: this.getId(), layerName: await this.getDisplayName(this.getSource()), prevDataRequest: this.getSourceDataRequest(), - requestMeta: { - ...syncContext.dataFilters, - fieldNames: this.getSource().getFieldNames(), - geogridPrecision: this.getSource().getGeoGridPrecision(syncContext.dataFilters.zoom), - sourceQuery: sourceQuery ? sourceQuery : undefined, - applyGlobalQuery: this.getSource().getApplyGlobalQuery(), - applyGlobalTime: this.getSource().getApplyGlobalTime(), - sourceMeta: this.getSource().getSyncMeta(), - }, + requestMeta: buildVectorRequestMeta( + this.getSource(), + this.getSource().getFieldNames(), + syncContext.dataFilters, + this.getQuery(), + syncContext.isForceRefresh + ), syncContext, source: this.getSource(), getUpdateDueToTimeslice: () => { @@ -194,7 +192,7 @@ export class HeatmapLayer extends AbstractLayer { layerId: this.getId(), syncContext, source: this.getSource(), - sourceQuery: this.getQuery() as MapQuery, + sourceQuery: this.getQuery(), }); } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.test.ts b/x-pack/plugins/maps/public/classes/layers/layer.test.ts index d3d8a94e175eb..dcc183c5c1741 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/layer.test.ts @@ -84,6 +84,7 @@ describe('cloneDescriptor', () => { type: SOURCE_TYPES.ES_TERM_SOURCE, applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, }, }, ], diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts index 74ab35e6cb360..939d174798ca1 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts @@ -61,6 +61,7 @@ describe('createLayerDescriptor', () => { type: 'avg', }, ], + applyForceRefresh: true, term: 'client.geo.country_iso_code', type: 'ES_TERM_SOURCE', whereQuery: { @@ -201,6 +202,7 @@ describe('createLayerDescriptor', () => { ], requestType: 'heatmap', resolution: 'MOST_FINE', + applyForceRefresh: true, type: 'ES_GEO_GRID', }, style: { @@ -245,6 +247,7 @@ describe('createLayerDescriptor', () => { ], requestType: 'point', resolution: 'MOST_FINE', + applyForceRefresh: true, type: 'ES_GEO_GRID', }, style: { diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts index 0b57afb38d585..d55040172f830 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts @@ -179,6 +179,7 @@ export function createLayerDescriptor({ whereQuery: apmSourceQuery, applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, }, }, ], diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.test.ts b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.test.ts index a3a3e8b20f678..cc6a7dfd9e796 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.test.ts @@ -47,6 +47,7 @@ describe('createLayerDescriptor', () => { geoField: 'client.geo.location', id: '12345', indexPatternId: 'id', + applyForceRefresh: true, scalingType: 'TOP_HITS', sortField: '', sortOrder: 'desc', @@ -156,6 +157,7 @@ describe('createLayerDescriptor', () => { geoField: 'server.geo.location', id: '12345', indexPatternId: 'id', + applyForceRefresh: true, scalingType: 'TOP_HITS', sortField: '', sortOrder: 'desc', @@ -274,6 +276,7 @@ describe('createLayerDescriptor', () => { type: 'sum', }, ], + applyForceRefresh: true, sourceGeoField: 'client.geo.location', type: 'ES_PEW_PEW', }, @@ -386,6 +389,7 @@ describe('createLayerDescriptor', () => { geoField: 'source.geo.location', id: '12345', indexPatternId: 'id', + applyForceRefresh: true, scalingType: 'TOP_HITS', sortField: '', sortOrder: 'desc', @@ -495,6 +499,7 @@ describe('createLayerDescriptor', () => { geoField: 'destination.geo.location', id: '12345', indexPatternId: 'id', + applyForceRefresh: true, scalingType: 'TOP_HITS', sortField: '', sortOrder: 'desc', @@ -613,6 +618,7 @@ describe('createLayerDescriptor', () => { type: 'sum', }, ], + applyForceRefresh: true, sourceGeoField: 'source.geo.location', type: 'ES_PEW_PEW', }, @@ -724,6 +730,7 @@ describe('createLayerDescriptor', () => { filterByMapBounds: true, geoField: 'client.geo.location', id: '12345', + applyForceRefresh: true, indexPatternId: 'id', scalingType: 'TOP_HITS', sortField: '', @@ -835,6 +842,7 @@ describe('createLayerDescriptor', () => { id: '12345', indexPatternId: 'id', scalingType: 'TOP_HITS', + applyForceRefresh: true, sortField: '', sortOrder: 'desc', tooltipProperties: [ @@ -952,6 +960,7 @@ describe('createLayerDescriptor', () => { type: 'sum', }, ], + applyForceRefresh: true, sourceGeoField: 'client.geo.location', type: 'ES_PEW_PEW', }, diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx index 6277411fa053a..0d365cc5fc8c4 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx @@ -38,7 +38,6 @@ import { } from '../../../../common/descriptor_types'; import { MVTSingleLayerVectorSourceConfig } from '../../sources/mvt_single_layer_vector_source/types'; import { canSkipSourceUpdate } from '../../util/can_skip_fetch'; -import { isRefreshOnlyQuery } from '../../util/is_refresh_only_query'; import { CustomIconAndTooltipContent } from '../layer'; export class TiledVectorLayer extends VectorLayer { @@ -113,9 +112,11 @@ export class TiledVectorLayer extends VectorLayer { stopLoading, onLoadError, dataFilters, + isForceRefresh, }: DataRequestContext) { const requestToken: symbol = Symbol(`layer-${this.getId()}-${SOURCE_DATA_REQUEST_ID}`); - const searchFilters: VectorSourceRequestMeta = await this._getSearchFilters( + const requestMeta: VectorSourceRequestMeta = await this._getVectorSourceRequestMeta( + isForceRefresh, dataFilters, this.getSource(), this._style as IVectorStyle @@ -132,7 +133,7 @@ export class TiledVectorLayer extends VectorLayer { extentAware: false, // spatial extent knowledge is already fully automated by tile-loading based on pan-zooming source: this.getSource(), prevDataRequest, - nextMeta: searchFilters, + nextRequestMeta: requestMeta, getUpdateDueToTimeslice: (timeslice?: Timeslice) => { // TODO use meta features to determine if tiles already contain features for timeslice. return true; @@ -145,18 +146,17 @@ export class TiledVectorLayer extends VectorLayer { } } - startLoading(SOURCE_DATA_REQUEST_ID, requestToken, searchFilters); + startLoading(SOURCE_DATA_REQUEST_ID, requestToken, requestMeta); try { - const prevMeta = prevDataRequest ? prevDataRequest.getMeta() : undefined; const prevData = prevDataRequest ? (prevDataRequest.getData() as MVTSingleLayerVectorSourceConfig) : undefined; const urlToken = - !prevData || isRefreshOnlyQuery(prevMeta ? prevMeta.query : undefined, searchFilters.query) + !prevData || (requestMeta.isForceRefresh && requestMeta.applyForceRefresh) ? uuid() : prevData.urlToken; - const newUrlTemplateAndMeta = await this._source.getUrlTemplateWithMeta(searchFilters); + const newUrlTemplateAndMeta = await this._source.getUrlTemplateWithMeta(requestMeta); let urlTemplate; if (newUrlTemplateAndMeta.refreshTokenParamName) { diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/utils.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/utils.tsx index 346e59f60af32..6bc72f09e9387 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/utils.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/utils.tsx @@ -7,6 +7,7 @@ import { FeatureCollection } from 'geojson'; import type { Map as MbMap } from '@kbn/mapbox-gl'; +import type { Query } from 'src/plugins/data/common'; import { EMPTY_FEATURE_COLLECTION, SOURCE_BOUNDS_DATA_REQUEST_ID, @@ -14,9 +15,8 @@ import { VECTOR_SHAPE_TYPE, } from '../../../../common/constants'; import { - DataMeta, + DataRequestMeta, MapExtent, - MapQuery, Timeslice, VectorSourceRequestMeta, } from '../../../../common/descriptor_types'; @@ -77,15 +77,17 @@ export async function syncVectorSource({ } = syncContext; const dataRequestId = SOURCE_DATA_REQUEST_ID; const requestToken = Symbol(`${layerId}-${dataRequestId}`); - const canSkipFetch = syncContext.forceRefresh + + const canSkipFetch = syncContext.forceRefreshDueToDrawing ? false : await canSkipSourceUpdate({ source, prevDataRequest, - nextMeta: requestMeta, + nextRequestMeta: requestMeta, extentAware: source.isFilterByMapBounds(), getUpdateDueToTimeslice, }); + if (canSkipFetch) { return { refreshed: false, @@ -113,11 +115,11 @@ export async function syncVectorSource({ ) { layerFeatureCollection.features.push(...getCentroidFeatures(layerFeatureCollection)); } - const responseMeta: DataMeta = meta ? { ...meta } : {}; + const responseMeta: DataRequestMeta = meta ? { ...meta } : {}; if (requestMeta.applyGlobalTime && (await source.isTimeAware())) { - const timesiceMaskField = await source.getTimesliceMaskFieldName(); - if (timesiceMaskField) { - responseMeta.timesiceMaskField = timesiceMaskField; + const timesliceMaskField = await source.getTimesliceMaskFieldName(); + if (timesliceMaskField) { + responseMeta.timesliceMaskField = timesliceMaskField; } } stopLoading(dataRequestId, requestToken, layerFeatureCollection, responseMeta); @@ -142,7 +144,7 @@ export async function getVectorSourceBounds({ layerId: string; syncContext: DataRequestContext; source: IVectorSource; - sourceQuery: MapQuery | null; + sourceQuery: Query | null; }): Promise { const { startLoading, stopLoading, registerCancelCallback, dataFilters } = syncContext; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 54e0c00141cd3..c4903ddb325b2 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -11,6 +11,7 @@ import type { AnyLayer as MbLayer, GeoJSONSource as MbGeoJSONSource, } from '@kbn/mapbox-gl'; +import type { Query } from 'src/plugins/data/common'; import { Feature, FeatureCollection, GeoJsonProperties, Geometry, Position } from 'geojson'; import _ from 'lodash'; import { EuiIcon } from '@elastic/eui'; @@ -48,14 +49,13 @@ import { } from '../../util/mb_filter_expressions'; import { DynamicStylePropertyOptions, - MapFilters, - MapQuery, + DataFilters, StyleMetaDescriptor, Timeslice, - VectorJoinSourceRequestMeta, VectorLayerDescriptor, VectorSourceRequestMeta, VectorStyleRequestMeta, + VectorJoinSourceRequestMeta, } from '../../../../common/descriptor_types'; import { ISource } from '../../sources/source'; import { IVectorSource } from '../../sources/vector_source'; @@ -70,6 +70,7 @@ import { PropertiesMap } from '../../../../common/elasticsearch_util'; import { ITermJoinSource } from '../../sources/term_join_source'; import { addGeoJsonMbSource, getVectorSourceBounds, syncVectorSource } from './utils'; import { JoinState, performInnerJoins } from './perform_inner_joins'; +import { buildVectorRequestMeta } from '../build_vector_request_meta'; export interface VectorLayerArguments { source: IVectorSource; @@ -266,7 +267,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { layerId: this.getId(), syncContext, source: this.getSource(), - sourceQuery: this.getQuery() as MapQuery, + sourceQuery: this.getQuery(), }); } @@ -332,29 +333,31 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { onLoadError, registerCancelCallback, dataFilters, + isForceRefresh, }: { join: InnerJoin } & DataRequestContext): Promise { const joinSource = join.getRightJoinSource(); const sourceDataId = join.getSourceDataRequestId(); const requestToken = Symbol(`layer-join-refresh:${this.getId()} - ${sourceDataId}`); - const searchFilters: VectorJoinSourceRequestMeta = { - ...dataFilters, - fieldNames: joinSource.getFieldNames(), - sourceQuery: joinSource.getWhereQuery(), - applyGlobalQuery: joinSource.getApplyGlobalQuery(), - applyGlobalTime: joinSource.getApplyGlobalTime(), - sourceMeta: joinSource.getSyncMeta(), - }; - const prevDataRequest = this.getDataRequest(sourceDataId); + const joinRequestMeta: VectorJoinSourceRequestMeta = buildVectorRequestMeta( + joinSource, + joinSource.getFieldNames(), + dataFilters, + joinSource.getWhereQuery(), + isForceRefresh + ) as VectorJoinSourceRequestMeta; + + const prevDataRequest = this.getDataRequest(sourceDataId); const canSkipFetch = await canSkipSourceUpdate({ source: joinSource, prevDataRequest, - nextMeta: searchFilters, + nextRequestMeta: joinRequestMeta, extentAware: false, // join-sources are term-aggs that are spatially unaware (e.g. ESTermSource/TableSource). getUpdateDueToTimeslice: () => { return true; }, }); + if (canSkipFetch) { return { dataHasChanged: false, @@ -364,10 +367,10 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { } try { - startLoading(sourceDataId, requestToken, searchFilters); + startLoading(sourceDataId, requestToken, joinRequestMeta); const leftSourceName = await this._source.getDisplayName(); const propertiesMap = await joinSource.getPropertiesMap( - searchFilters, + joinRequestMeta, leftSourceName, join.getLeftField().getName(), registerCancelCallback.bind(null, requestToken) @@ -396,8 +399,9 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { return await Promise.all(joinSyncs); } - async _getSearchFilters( - dataFilters: MapFilters, + async _getVectorSourceRequestMeta( + isForceRefresh: boolean, + dataFilters: DataFilters, source: IVectorSource, style: IVectorStyle ): Promise { @@ -411,17 +415,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { if (timesliceMaskFieldName) { fieldNames.push(timesliceMaskFieldName); } - - const sourceQuery = this.getQuery() as MapQuery; - return { - ...dataFilters, - fieldNames: _.uniq(fieldNames).sort(), - geogridPrecision: source.getGeoGridPrecision(dataFilters.zoom), - sourceQuery: sourceQuery ? sourceQuery : undefined, - applyGlobalQuery: source.getApplyGlobalQuery(), - applyGlobalTime: source.getApplyGlobalTime(), - sourceMeta: source.getSyncMeta(), - }; + return buildVectorRequestMeta(source, fieldNames, dataFilters, this.getQuery(), isForceRefresh); } async _syncSourceStyleMeta( @@ -429,7 +423,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { source: IVectorSource, style: IVectorStyle ) { - const sourceQuery = this.getQuery() as MapQuery; + const sourceQuery = this.getQuery(); return this._syncStyleMeta({ source, style, @@ -481,7 +475,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { dataRequestId: string; dynamicStyleProps: Array>; source: IVectorSource | ITermJoinSource; - sourceQuery?: MapQuery; + sourceQuery?: Query; style: IVectorStyle; } & DataRequestContext) { if (!source.isESSource() || dynamicStyleProps.length === 0) { @@ -641,7 +635,12 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { layerId: this.getId(), layerName: await this.getDisplayName(source), prevDataRequest: this.getSourceDataRequest(), - requestMeta: await this._getSearchFilters(syncContext.dataFilters, source, style), + requestMeta: await this._getVectorSourceRequestMeta( + syncContext.isForceRefresh, + syncContext.dataFilters, + source, + style + ), syncContext, source, getUpdateDueToTimeslice: (timeslice?: Timeslice) => { @@ -995,9 +994,9 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { } const prevMeta = this.getSourceDataRequest()?.getMeta(); - return prevMeta !== undefined && prevMeta.timesiceMaskField !== undefined + return prevMeta !== undefined && prevMeta.timesliceMaskField !== undefined ? { - timesiceMaskField: prevMeta.timesiceMaskField, + timesliceMaskField: prevMeta.timesliceMaskField, timeslice, } : undefined; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.test.ts b/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.test.ts index 20627f42b3d2d..fe3c6d27ef588 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.test.ts @@ -7,7 +7,7 @@ import { ITileLayerArguments } from '../tile_layer/tile_layer'; import { SOURCE_TYPES } from '../../../../common/constants'; -import { MapFilters, XYZTMSSourceDescriptor } from '../../../../common/descriptor_types'; +import { DataFilters, XYZTMSSourceDescriptor } from '../../../../common/descriptor_types'; import { ITMSSource, AbstractTMSSource } from '../../sources/tms_source'; import { ILayer } from '../layer'; import { VectorTileLayer } from './vector_tile_layer'; @@ -63,7 +63,7 @@ describe('VectorTileLayer', () => { onLoadError: (requestId: string, token: string, message: string) => { actualErrorMessage = message; }, - dataFilters: ({ foo: 'bar' } as unknown) as MapFilters, + dataFilters: ({ foo: 'bar' } as unknown) as DataFilters, } as unknown) as DataRequestContext; await layer.syncData(mockContext); diff --git a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.test.ts index 360f00b486a38..7db3652011e9a 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.test.ts @@ -40,6 +40,7 @@ class TestESAggSource extends AbstractESAggSource { metrics, applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, }, [] ); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts index efbb755f2a1f7..41d5715e47b8e 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -155,15 +155,16 @@ describe('ESGeoGridSource', () => { extent, applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, fieldNames: [], buffer: extent, sourceQuery: { query: '', language: 'KQL', - queryLastTriggeredAt: '2019-04-25T20:53:22.331Z', }, sourceMeta: null, zoom: 0, + isForceRefresh: false, }; describe('getGeoJsonWithMeta', () => { @@ -315,7 +316,7 @@ describe('ESGeoGridSource', () => { expect(urlTemplateWithMeta.minSourceZoom).toBe(0); expect(urlTemplateWithMeta.maxSourceZoom).toBe(24); expect(urlTemplateWithMeta.urlTemplate).toEqual( - "rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point" + "rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point" ); }); @@ -327,7 +328,7 @@ describe('ESGeoGridSource', () => { expect( urlTemplateWithMeta.urlTemplate.startsWith( - "rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point&searchSessionId=1" + "rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point&searchSessionId=1" ) ).toBe(true); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.test.ts index 0c15afff6b051..4a818d898a190 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.test.ts @@ -20,7 +20,7 @@ describe('getSourceTooltipContent', () => { const sourceDataRequest = new DataRequest({ data: {}, dataId: 'source', - dataMeta: { + dataRequestMeta: { areResultsTrimmed: false, areEntitiesTrimmed: false, entityCount: 70, @@ -39,7 +39,7 @@ describe('getSourceTooltipContent', () => { const sourceDataRequest = new DataRequest({ data: {}, dataId: 'source', - dataMeta: { + dataRequestMeta: { areResultsTrimmed: true, areEntitiesTrimmed: true, entityCount: 1000, @@ -58,7 +58,7 @@ describe('getSourceTooltipContent', () => { const sourceDataRequest = new DataRequest({ data: {}, dataId: 'source', - dataMeta: { + dataRequestMeta: { areResultsTrimmed: false, areEntitiesTrimmed: false, entityCount: 70, @@ -77,7 +77,7 @@ describe('getSourceTooltipContent', () => { const sourceDataRequest = new DataRequest({ data: {}, dataId: 'source', - dataMeta: { + dataRequestMeta: { areResultsTrimmed: true, areEntitiesTrimmed: true, entityCount: 1000, diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.test.ts b/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.test.ts index e7711a6e28e01..0c68bf6d832ad 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/create_layer_descriptor.test.ts @@ -41,6 +41,7 @@ test('Should create layer descriptor', () => { geoField: 'myGeoField', id: '12345', indexPatternId: 'myIndexPattern', + applyForceRefresh: true, scalingType: 'CLUSTERS', sortField: '', sortOrder: 'desc', diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts index 1a5ea8bb14e0e..5bff5d69aeab7 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts @@ -102,11 +102,12 @@ describe('ESSearchSource', () => { sourceQuery: { query: 'tooltipField: foobar', language: 'KQL', - queryLastTriggeredAt: '2019-04-25T20:53:22.331Z', }, sourceMeta: null, applyGlobalQuery: true, applyGlobalTime: true, + applyForceRefresh: true, + isForceRefresh: false, }; it('Should only include required props', async () => { @@ -116,7 +117,7 @@ describe('ESSearchSource', () => { }); const urlTemplateWithMeta = await esSearchSource.getUrlTemplateWithMeta(searchFilters); expect(urlTemplateWithMeta.urlTemplate).toBe( - `rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:(),title:'foobar-title-*')),'1':('0':size,'1':1000),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:(),title:'foobar-title-*')),'5':('0':query,'1':(language:KQL,query:'tooltipField: foobar',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':fieldsFromSource,'1':!(tooltipField,styleField)),'7':('0':source,'1':!(tooltipField,styleField))))&geoFieldType=geo_shape` + `rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:(),title:'foobar-title-*')),'1':('0':size,'1':1000),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:(),title:'foobar-title-*')),'5':('0':query,'1':(language:KQL,query:'tooltipField: foobar')),'6':('0':fieldsFromSource,'1':!(tooltipField,styleField)),'7':('0':source,'1':!(tooltipField,styleField))))&geoFieldType=geo_shape` ); }); @@ -130,7 +131,7 @@ describe('ESSearchSource', () => { searchSessionId: '1', }); expect(urlTemplateWithMeta.urlTemplate).toBe( - `rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:(),title:'foobar-title-*')),'1':('0':size,'1':1000),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:(),title:'foobar-title-*')),'5':('0':query,'1':(language:KQL,query:'tooltipField: foobar',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':fieldsFromSource,'1':!(tooltipField,styleField)),'7':('0':source,'1':!(tooltipField,styleField))))&geoFieldType=geo_shape&searchSessionId=1` + `rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:(),title:'foobar-title-*')),'1':('0':size,'1':1000),'2':('0':filter,'1':!()),'3':('0':query),'4':('0':index,'1':(fields:(),title:'foobar-title-*')),'5':('0':query,'1':(language:KQL,query:'tooltipField: foobar')),'6':('0':fieldsFromSource,'1':!(tooltipField,styleField)),'7':('0':source,'1':!(tooltipField,styleField))))&geoFieldType=geo_shape&searchSessionId=1` ); }); }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx index 1ca7ddb586293..2b847d218434d 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx @@ -48,7 +48,7 @@ import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; import { ESDocField } from '../../fields/es_doc_field'; import { registerSource } from '../source_registry'; import { - DataMeta, + DataRequestMeta, ESSearchSourceDescriptor, Timeslice, VectorSourceRequestMeta, @@ -853,7 +853,7 @@ export class ESSearchSource extends AbstractESSource implements ITiledSingleLaye return indexPattern.timeFieldName ? indexPattern.timeFieldName : null; } - getUpdateDueToTimeslice(prevMeta: DataMeta, timeslice?: Timeslice): boolean { + getUpdateDueToTimeslice(prevMeta: DataRequestMeta, timeslice?: Timeslice): boolean { if (this._isTopHits() || this._descriptor.scalingType === SCALING_TYPES.MVT) { return true; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts index ce8991bb63ce6..b57ee6a36894f 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts @@ -8,7 +8,8 @@ import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; import { Filter, IndexPatternField, IndexPattern, ISearchSource } from 'src/plugins/data/public'; -import { AbstractVectorSource, BoundsFilters } from '../vector_source'; +import type { Query } from 'src/plugins/data/common'; +import { AbstractVectorSource, BoundsRequestMeta } from '../vector_source'; import { getAutocompleteService, getIndexPatternService, @@ -26,7 +27,6 @@ import { AbstractSourceDescriptor, DynamicStylePropertyOptions, MapExtent, - MapQuery, VectorJoinSourceRequestMeta, VectorSourceRequestMeta, } from '../../../../common/descriptor_types'; @@ -60,7 +60,7 @@ export interface IESSource extends IVectorSource { style: IVectorStyle; dynamicStyleProps: Array>; registerCancelCallback: (callback: () => void) => void; - sourceQuery?: MapQuery; + sourceQuery?: Query; timeFilters: TimeRange; searchSessionId?: string; }): Promise; @@ -88,6 +88,8 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource typeof descriptor.applyGlobalQuery !== 'undefined' ? descriptor.applyGlobalQuery : true, applyGlobalTime: typeof descriptor.applyGlobalTime !== 'undefined' ? descriptor.applyGlobalTime : true, + applyForceRefresh: + typeof descriptor.applyForceRefresh !== 'undefined' ? descriptor.applyForceRefresh : true, }; } @@ -108,11 +110,11 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource return this._descriptor.applyGlobalTime; } - isFieldAware(): boolean { - return true; + getApplyForceRefresh(): boolean { + return this._descriptor.applyForceRefresh; } - isRefreshTimerAware(): boolean { + isFieldAware(): boolean { return true; } @@ -197,7 +199,7 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource } async makeSearchSource( - searchFilters: VectorSourceRequestMeta | VectorJoinSourceRequestMeta | BoundsFilters, + searchFilters: VectorSourceRequestMeta | VectorJoinSourceRequestMeta | BoundsRequestMeta, limit: number, initialSearchContext?: object ): Promise { @@ -253,7 +255,7 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource } async getBoundsForFilters( - boundsFilters: BoundsFilters, + boundsFilters: BoundsRequestMeta, registerCancelCallback: (callback: () => void) => void ): Promise { const searchSource = await this.makeSearchSource(boundsFilters, 0); @@ -421,7 +423,7 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource style: IVectorStyle; dynamicStyleProps: Array>; registerCancelCallback: (callback: () => void) => void; - sourceQuery?: MapQuery; + sourceQuery?: Query; timeFilters: TimeRange; searchSessionId?: string; }): Promise { diff --git a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file.test.ts b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file.test.ts index 6f7d5aa91e2b8..9e21f16d7f30a 100644 --- a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file.test.ts @@ -6,7 +6,7 @@ */ import { GeoJsonFileSource } from './geojson_file_source'; -import { BoundsFilters } from '../vector_source'; +import { BoundsRequestMeta } from '../vector_source'; import { FIELD_ORIGIN } from '../../../../common/constants'; describe('GeoJsonFileSource', () => { @@ -20,7 +20,7 @@ describe('GeoJsonFileSource', () => { it('should get null bounds', async () => { const geojsonFileSource = new GeoJsonFileSource({}); expect( - await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsFilters, () => {}) + await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsRequestMeta, () => {}) ).toEqual(null); }); @@ -51,7 +51,7 @@ describe('GeoJsonFileSource', () => { expect(geojsonFileSource.isBoundsAware()).toBe(true); expect( - await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsFilters, () => {}) + await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsRequestMeta, () => {}) ).toEqual({ maxLat: 3, maxLon: 2, diff --git a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts index 592c2f852f0e7..4de29fde1253c 100644 --- a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts @@ -6,7 +6,7 @@ */ import { Feature, FeatureCollection } from 'geojson'; -import { AbstractVectorSource, BoundsFilters, GeoJsonWithMeta } from '../vector_source'; +import { AbstractVectorSource, BoundsRequestMeta, GeoJsonWithMeta } from '../vector_source'; import { EMPTY_FEATURE_COLLECTION, FIELD_ORIGIN, SOURCE_TYPES } from '../../../../common/constants'; import { InlineFieldDescriptor, @@ -103,7 +103,7 @@ export class GeoJsonFileSource extends AbstractVectorSource { } async getBoundsForFilters( - boundsFilters: BoundsFilters, + boundsFilters: BoundsRequestMeta, registerCancelCallback: (callback: () => void) => void ): Promise { const featureCollection = (this._descriptor as GeojsonFileSourceDescriptor).__featureCollection; diff --git a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx index 6911cbabdf971..d041e0d3ad5de 100644 --- a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source.tsx @@ -10,7 +10,7 @@ import uuid from 'uuid/v4'; import React from 'react'; import { GeoJsonProperties, Geometry, Position } from 'geojson'; import { AbstractSource, ImmutableSourceProperty, SourceEditorArgs } from '../source'; -import { BoundsFilters, GeoJsonWithMeta } from '../vector_source'; +import { BoundsRequestMeta, GeoJsonWithMeta } from '../vector_source'; import { ITiledSingleLayerVectorSource } from '../tiled_single_layer_vector_source'; import { FIELD_ORIGIN, @@ -190,7 +190,7 @@ export class MVTSingleLayerVectorSource } async getBoundsForFilters( - boundsFilters: BoundsFilters, + boundsFilters: BoundsRequestMeta, registerCancelCallback: (callback: () => void) => void ): Promise { return null; diff --git a/x-pack/plugins/maps/public/classes/sources/source.ts b/x-pack/plugins/maps/public/classes/sources/source.ts index 0ecbde06cf3e2..5b2fc16d18b41 100644 --- a/x-pack/plugins/maps/public/classes/sources/source.ts +++ b/x-pack/plugins/maps/public/classes/sources/source.ts @@ -16,7 +16,7 @@ import { FieldFormatter, LAYER_TYPE, MAX_ZOOM, MIN_ZOOM } from '../../../common/ import { AbstractSourceDescriptor, Attribution, - DataMeta, + DataRequestMeta, Timeslice, } from '../../../common/descriptor_types'; import { LICENSED_FEATURES } from '../../licensed_features'; @@ -47,7 +47,6 @@ export interface ISource { isFilterByMapBounds(): boolean; isGeoGridPrecisionAware(): boolean; isQueryAware(): boolean; - isRefreshTimerAware(): boolean; isTimeAware(): Promise; getImmutableProperties(): Promise; getAttributionProvider(): (() => Promise) | null; @@ -60,6 +59,7 @@ export interface ISource { getFieldNames(): string[]; getApplyGlobalQuery(): boolean; getApplyGlobalTime(): boolean; + getApplyForceRefresh(): boolean; getIndexPatternIds(): string[]; getQueryableIndexPatternIds(): string[]; getGeoGridPrecision(zoom: number): number; @@ -69,7 +69,7 @@ export interface ISource { getMinZoom(): number; getMaxZoom(): number; getLicensedFeatures(): Promise; - getUpdateDueToTimeslice(prevMeta: DataMeta, timeslice?: Timeslice): boolean; + getUpdateDueToTimeslice(prevMeta: DataRequestMeta, timeslice?: Timeslice): boolean; } export class AbstractSource implements ISource { @@ -115,10 +115,6 @@ export class AbstractSource implements ISource { return false; } - isRefreshTimerAware(): boolean { - return false; - } - isGeoGridPrecisionAware(): boolean { return false; } @@ -143,6 +139,10 @@ export class AbstractSource implements ISource { return false; } + getApplyForceRefresh(): boolean { + return false; + } + getIndexPatternIds(): string[] { return []; } @@ -201,7 +201,7 @@ export class AbstractSource implements ISource { return []; } - getUpdateDueToTimeslice(prevMeta: DataMeta, timeslice?: Timeslice): boolean { + getUpdateDueToTimeslice(prevMeta: DataRequestMeta, timeslice?: Timeslice): boolean { return true; } } diff --git a/x-pack/plugins/maps/public/classes/sources/table_source/table_source.test.ts b/x-pack/plugins/maps/public/classes/sources/table_source/table_source.test.ts index 337cc2d601abd..62404cbe942e3 100644 --- a/x-pack/plugins/maps/public/classes/sources/table_source/table_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/table_source/table_source.test.ts @@ -5,11 +5,11 @@ * 2.0. */ +import type { Query } from 'src/plugins/data/common'; import { TableSource } from './table_source'; import { FIELD_ORIGIN } from '../../../../common/constants'; import { - MapFilters, - MapQuery, + DataFilters, VectorJoinSourceRequestMeta, VectorSourceSyncMeta, } from '../../../../common/descriptor_types'; @@ -178,12 +178,12 @@ describe('TableSource', () => { try { await tableSource.getGeoJsonWithMeta( 'foobar', - ({} as unknown) as MapFilters & { + ({} as unknown) as DataFilters & { applyGlobalQuery: boolean; applyGlobalTime: boolean; fieldNames: string[]; geogridPrecision?: number; - sourceQuery?: MapQuery; + sourceQuery?: Query; sourceMeta: VectorSourceSyncMeta; }, () => {}, diff --git a/x-pack/plugins/maps/public/classes/sources/table_source/table_source.ts b/x-pack/plugins/maps/public/classes/sources/table_source/table_source.ts index 372fb4983d7cc..8730ea7e3d02b 100644 --- a/x-pack/plugins/maps/public/classes/sources/table_source/table_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/table_source/table_source.ts @@ -6,11 +6,11 @@ */ import uuid from 'uuid'; +import type { Query } from 'src/plugins/data/common'; import { FIELD_ORIGIN, SOURCE_TYPES, VECTOR_SHAPE_TYPE } from '../../../../common/constants'; import { MapExtent, - MapFilters, - MapQuery, + DataFilters, TableSourceDescriptor, VectorJoinSourceRequestMeta, VectorSourceSyncMeta, @@ -19,10 +19,9 @@ import { Adapters } from '../../../../../../../src/plugins/inspector/common/adap import { ITermJoinSource } from '../term_join_source'; import { BucketProperties, PropertiesMap } from '../../../../common/elasticsearch_util'; import { IField } from '../../fields/field'; -import { Query } from '../../../../../../../src/plugins/data/common/query'; import { AbstractVectorSource, - BoundsFilters, + BoundsRequestMeta, GeoJsonWithMeta, IVectorSource, SourceTooltipConfig, @@ -156,7 +155,7 @@ export class TableSource extends AbstractVectorSource implements ITermJoinSource } async getBoundsForFilters( - boundsFilters: BoundsFilters, + boundsFilters: BoundsRequestMeta, registerCancelCallback: (callback: () => void) => void ): Promise { return null; @@ -187,12 +186,12 @@ export class TableSource extends AbstractVectorSource implements ITermJoinSource // Could be useful to implement, e.g. to preview raw csv data async getGeoJsonWithMeta( layerName: string, - searchFilters: MapFilters & { + searchFilters: DataFilters & { applyGlobalQuery: boolean; applyGlobalTime: boolean; fieldNames: string[]; geogridPrecision?: number; - sourceQuery?: MapQuery; + sourceQuery?: Query; sourceMeta: VectorSourceSyncMeta; }, registerCancelCallback: (callback: () => void) => void, diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index 05f0124310bd8..bf0752d54c426 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import type { Query } from 'src/plugins/data/common'; import { FeatureCollection, GeoJsonProperties, Geometry, Position } from 'geojson'; import { Filter, TimeRange } from 'src/plugins/data/public'; import { VECTOR_SHAPE_TYPE } from '../../../../common/constants'; @@ -14,7 +15,6 @@ import { IField } from '../../fields/field'; import { ESSearchSourceResponseMeta, MapExtent, - MapQuery, Timeslice, VectorSourceRequestMeta, VectorSourceSyncMeta, @@ -34,12 +34,12 @@ export interface GeoJsonWithMeta { meta?: GeoJsonFetchMeta; } -export interface BoundsFilters { +export interface BoundsRequestMeta { applyGlobalQuery: boolean; applyGlobalTime: boolean; filters: Filter[]; - query?: MapQuery; - sourceQuery?: MapQuery; + query?: Query; + sourceQuery?: Query; timeFilters: TimeRange; timeslice?: Timeslice; } @@ -47,7 +47,7 @@ export interface BoundsFilters { export interface IVectorSource extends ISource { getTooltipProperties(properties: GeoJsonProperties): Promise; getBoundsForFilters( - boundsFilters: BoundsFilters, + layerDataFilters: BoundsRequestMeta, registerCancelCallback: (callback: () => void) => void ): Promise; getGeoJsonWithMeta( @@ -103,7 +103,7 @@ export class AbstractVectorSource extends AbstractSource implements IVectorSourc } async getBoundsForFilters( - boundsFilters: BoundsFilters, + boundsFilters: BoundsRequestMeta, registerCancelCallback: (callback: () => void) => void ): Promise { return null; diff --git a/x-pack/plugins/maps/public/classes/util/can_skip_fetch.test.js b/x-pack/plugins/maps/public/classes/util/can_skip_fetch.test.ts similarity index 81% rename from x-pack/plugins/maps/public/classes/util/can_skip_fetch.test.js rename to x-pack/plugins/maps/public/classes/util/can_skip_fetch.test.ts index da3cbb9055d43..16d25469025f4 100644 --- a/x-pack/plugins/maps/public/classes/util/can_skip_fetch.test.js +++ b/x-pack/plugins/maps/public/classes/util/can_skip_fetch.test.ts @@ -7,6 +7,8 @@ import { canSkipSourceUpdate, updateDueToExtent } from './can_skip_fetch'; import { DataRequest } from './data_request'; +import { Filter } from 'src/plugins/data/common'; +import { ISource } from '../sources/source'; describe('updateDueToExtent', () => { it('should be false when buffers are the same', async () => { @@ -91,9 +93,6 @@ describe('canSkipSourceUpdate', () => { isTimeAware: () => { return false; }, - isRefreshTimerAware: () => { - return false; - }, isFilterByMapBounds: () => { return false; }, @@ -107,11 +106,10 @@ describe('canSkipSourceUpdate', () => { return false; }, }; - const prevFilters = []; + const prevFilters: Filter[] = []; const prevQuery = { language: 'kuery', query: 'machine.os.keyword : "win 7"', - queryLastTriggeredAt: '2019-04-25T20:53:22.331Z', }; describe('applyGlobalQuery is false', () => { @@ -119,7 +117,7 @@ describe('canSkipSourceUpdate', () => { const prevDataRequest = new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalQuery: prevApplyGlobalQuery, filters: prevFilters, query: prevQuery, @@ -128,16 +126,16 @@ describe('canSkipSourceUpdate', () => { }); it('can skip update when filter changes', async () => { - const nextMeta = { + const nextRequestMeta = { applyGlobalQuery: prevApplyGlobalQuery, - filters: [prevQuery], + filters: [({} as unknown) as Filter], query: prevQuery, }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -146,7 +144,7 @@ describe('canSkipSourceUpdate', () => { }); it('can skip update when query changes', async () => { - const nextMeta = { + const nextRequestMeta = { applyGlobalQuery: prevApplyGlobalQuery, filters: prevFilters, query: { @@ -156,9 +154,9 @@ describe('canSkipSourceUpdate', () => { }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -166,20 +164,19 @@ describe('canSkipSourceUpdate', () => { expect(canSkipUpdate).toBe(true); }); - it('can not skip update when query is refreshed', async () => { - const nextMeta = { + it('Should not skip refresh update when applyForceRefresh is true', async () => { + const nextRequestMeta = { applyGlobalQuery: prevApplyGlobalQuery, filters: prevFilters, - query: { - ...prevQuery, - queryLastTriggeredAt: 'sometime layer when Refresh button is clicked', - }, + query: prevQuery, + isForceRefresh: true, + applyForceRefresh: true, }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -187,17 +184,37 @@ describe('canSkipSourceUpdate', () => { expect(canSkipUpdate).toBe(false); }); + it('Should skip refresh update when applyForceRefresh is false', async () => { + const nextRequestMeta = { + applyGlobalQuery: prevApplyGlobalQuery, + filters: prevFilters, + query: prevQuery, + isForceRefresh: true, + applyForceRefresh: false, + }; + + const canSkipUpdate = await canSkipSourceUpdate({ + source: (queryAwareSourceMock as unknown) as ISource, + prevDataRequest, + nextRequestMeta, + extentAware: queryAwareSourceMock.isFilterByMapBounds(), + getUpdateDueToTimeslice, + }); + + expect(canSkipUpdate).toBe(true); + }); + it('can not skip update when applyGlobalQuery changes', async () => { - const nextMeta = { + const nextRequestMeta = { applyGlobalQuery: !prevApplyGlobalQuery, filters: prevFilters, query: prevQuery, }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -211,7 +228,7 @@ describe('canSkipSourceUpdate', () => { const prevDataRequest = new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalQuery: prevApplyGlobalQuery, filters: prevFilters, query: prevQuery, @@ -220,16 +237,16 @@ describe('canSkipSourceUpdate', () => { }); it('can not skip update when filter changes', async () => { - const nextMeta = { + const nextRequestMeta = { applyGlobalQuery: prevApplyGlobalQuery, - filters: [prevQuery], + filters: [({} as unknown) as Filter], query: prevQuery, }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -238,7 +255,7 @@ describe('canSkipSourceUpdate', () => { }); it('can not skip update when query changes', async () => { - const nextMeta = { + const nextRequestMeta = { applyGlobalQuery: prevApplyGlobalQuery, filters: prevFilters, query: { @@ -248,9 +265,9 @@ describe('canSkipSourceUpdate', () => { }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -259,19 +276,18 @@ describe('canSkipSourceUpdate', () => { }); it('can not skip update when query is refreshed', async () => { - const nextMeta = { + const nextRequestMeta = { applyGlobalQuery: prevApplyGlobalQuery, filters: prevFilters, - query: { - ...prevQuery, - queryLastTriggeredAt: 'sometime layer when Refresh button is clicked', - }, + query: prevQuery, + isForceRefresh: true, + applyForceRefresh: true, }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -280,16 +296,16 @@ describe('canSkipSourceUpdate', () => { }); it('can not skip update when applyGlobalQuery changes', async () => { - const nextMeta = { + const nextRequestMeta = { applyGlobalQuery: !prevApplyGlobalQuery, filters: prevFilters, query: prevQuery, }; const canSkipUpdate = await canSkipSourceUpdate({ - source: queryAwareSourceMock, + source: (queryAwareSourceMock as unknown) as ISource, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware: queryAwareSourceMock.isFilterByMapBounds(), getUpdateDueToTimeslice, }); @@ -305,9 +321,6 @@ describe('canSkipSourceUpdate', () => { isTimeAware: () => { return true; }, - isRefreshTimerAware: () => { - return false; - }, isFilterByMapBounds: () => { return false; }, @@ -326,15 +339,15 @@ describe('canSkipSourceUpdate', () => { describe('applyGlobalTime', () => { it('can not skip update when applyGlobalTime changes', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: createSourceMock(), + source: (createSourceMock() as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: false, }, extentAware: false, @@ -346,15 +359,15 @@ describe('canSkipSourceUpdate', () => { it('can skip update when applyGlobalTime does not change', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: createSourceMock(), + source: (createSourceMock() as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: true, }, extentAware: false, @@ -368,10 +381,10 @@ describe('canSkipSourceUpdate', () => { describe('timeFilters', () => { it('can not skip update when time range changes', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: createSourceMock(), + source: (createSourceMock() as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-15m', @@ -380,7 +393,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -396,10 +409,10 @@ describe('canSkipSourceUpdate', () => { it('can skip update when time range does not change', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: createSourceMock(), + source: (createSourceMock() as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-15m', @@ -408,7 +421,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-15m', @@ -424,10 +437,10 @@ describe('canSkipSourceUpdate', () => { it('can skip update when time range changes but applyGlobalTime is false', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: createSourceMock(), + source: (createSourceMock() as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: false, timeFilters: { from: 'now-15m', @@ -436,7 +449,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: false, timeFilters: { from: 'now-7d', @@ -455,10 +468,10 @@ describe('canSkipSourceUpdate', () => { const mockSource = createSourceMock(); it('can not skip update when timeslice changes (undefined => provided)', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: mockSource, + source: (mockSource as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -467,7 +480,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -487,10 +500,10 @@ describe('canSkipSourceUpdate', () => { it('can not skip update when timeslice changes', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: mockSource, + source: (mockSource as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -503,7 +516,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -523,10 +536,10 @@ describe('canSkipSourceUpdate', () => { it('can not skip update when timeslice changes (provided => undefined)', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: mockSource, + source: (mockSource as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -539,7 +552,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -555,10 +568,10 @@ describe('canSkipSourceUpdate', () => { it('can skip update when timeslice does not change', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: mockSource, + source: (mockSource as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -571,7 +584,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: true, timeFilters: { from: 'now-7d', @@ -591,10 +604,10 @@ describe('canSkipSourceUpdate', () => { it('can skip update when timeslice changes but applyGlobalTime is false', async () => { const canSkipUpdate = await canSkipSourceUpdate({ - source: mockSource, + source: (mockSource as unknown) as ISource, prevDataRequest: new DataRequest({ dataId: SOURCE_DATA_REQUEST_ID, - dataMeta: { + dataRequestMeta: { applyGlobalTime: false, timeFilters: { from: 'now-7d', @@ -607,7 +620,7 @@ describe('canSkipSourceUpdate', () => { }, data: {}, }), - nextMeta: { + nextRequestMeta: { applyGlobalTime: false, timeFilters: { from: 'now-7d', diff --git a/x-pack/plugins/maps/public/classes/util/can_skip_fetch.ts b/x-pack/plugins/maps/public/classes/util/can_skip_fetch.ts index b6f03ef3d1c63..69a5c73ba2933 100644 --- a/x-pack/plugins/maps/public/classes/util/can_skip_fetch.ts +++ b/x-pack/plugins/maps/public/classes/util/can_skip_fetch.ts @@ -8,15 +8,14 @@ import _ from 'lodash'; import turfBboxPolygon from '@turf/bbox-polygon'; import turfBooleanContains from '@turf/boolean-contains'; -import { isRefreshOnlyQuery } from './is_refresh_only_query'; import { ISource } from '../sources/source'; -import { DataMeta, Timeslice } from '../../../common/descriptor_types'; +import { DataRequestMeta, Timeslice } from '../../../common/descriptor_types'; import { DataRequest } from './data_request'; const SOURCE_UPDATE_REQUIRED = true; const NO_SOURCE_UPDATE_REQUIRED = false; -export function updateDueToExtent(prevMeta: DataMeta = {}, nextMeta: DataMeta = {}) { +export function updateDueToExtent(prevMeta: DataRequestMeta = {}, nextMeta: DataRequestMeta = {}) { const { buffer: previousBuffer } = prevMeta; const { buffer: newBuffer } = nextMeta; @@ -54,30 +53,28 @@ export function updateDueToExtent(prevMeta: DataMeta = {}, nextMeta: DataMeta = export async function canSkipSourceUpdate({ source, prevDataRequest, - nextMeta, + nextRequestMeta, extentAware, getUpdateDueToTimeslice, }: { source: ISource; prevDataRequest: DataRequest | undefined; - nextMeta: DataMeta; + nextRequestMeta: DataRequestMeta; extentAware: boolean; getUpdateDueToTimeslice: (timeslice?: Timeslice) => boolean; }): Promise { + const mustForceRefresh = nextRequestMeta.isForceRefresh && nextRequestMeta.applyForceRefresh; + if (mustForceRefresh) { + // Cannot skip + return false; + } + const timeAware = await source.isTimeAware(); - const refreshTimerAware = await source.isRefreshTimerAware(); const isFieldAware = source.isFieldAware(); const isQueryAware = source.isQueryAware(); const isGeoGridPrecisionAware = source.isGeoGridPrecisionAware(); - if ( - !timeAware && - !refreshTimerAware && - !extentAware && - !isFieldAware && - !isQueryAware && - !isGeoGridPrecisionAware - ) { + if (!timeAware && !extentAware && !isFieldAware && !isQueryAware && !isGeoGridPrecisionAware) { return !!prevDataRequest && prevDataRequest.hasDataOrRequestInProgress(); } @@ -93,26 +90,18 @@ export async function canSkipSourceUpdate({ let updateDueToTime = false; let updateDueToTimeslice = false; if (timeAware) { - updateDueToApplyGlobalTime = prevMeta.applyGlobalTime !== nextMeta.applyGlobalTime; - if (nextMeta.applyGlobalTime) { - updateDueToTime = !_.isEqual(prevMeta.timeFilters, nextMeta.timeFilters); - if (!_.isEqual(prevMeta.timeslice, nextMeta.timeslice)) { - updateDueToTimeslice = getUpdateDueToTimeslice(nextMeta.timeslice); + updateDueToApplyGlobalTime = prevMeta.applyGlobalTime !== nextRequestMeta.applyGlobalTime; + if (nextRequestMeta.applyGlobalTime) { + updateDueToTime = !_.isEqual(prevMeta.timeFilters, nextRequestMeta.timeFilters); + if (!_.isEqual(prevMeta.timeslice, nextRequestMeta.timeslice)) { + updateDueToTimeslice = getUpdateDueToTimeslice(nextRequestMeta.timeslice); } } } - let updateDueToRefreshTimer = false; - if (refreshTimerAware && nextMeta.refreshTimerLastTriggeredAt) { - updateDueToRefreshTimer = !_.isEqual( - prevMeta.refreshTimerLastTriggeredAt, - nextMeta.refreshTimerLastTriggeredAt - ); - } - let updateDueToFields = false; if (isFieldAware) { - updateDueToFields = !_.isEqual(prevMeta.fieldNames, nextMeta.fieldNames); + updateDueToFields = !_.isEqual(prevMeta.fieldNames, nextRequestMeta.fieldNames); } let updateDueToQuery = false; @@ -120,42 +109,41 @@ export async function canSkipSourceUpdate({ let updateDueToSourceQuery = false; let updateDueToApplyGlobalQuery = false; if (isQueryAware) { - updateDueToApplyGlobalQuery = prevMeta.applyGlobalQuery !== nextMeta.applyGlobalQuery; - updateDueToSourceQuery = !_.isEqual(prevMeta.sourceQuery, nextMeta.sourceQuery); - - if (nextMeta.applyGlobalQuery) { - updateDueToQuery = !_.isEqual(prevMeta.query, nextMeta.query); - updateDueToFilters = !_.isEqual(prevMeta.filters, nextMeta.filters); - } else { - // Global filters and query are not applied to layer search request so no re-fetch required. - // Exception is "Refresh" query. - updateDueToQuery = isRefreshOnlyQuery(prevMeta.query, nextMeta.query); + updateDueToApplyGlobalQuery = prevMeta.applyGlobalQuery !== nextRequestMeta.applyGlobalQuery; + updateDueToSourceQuery = !_.isEqual(prevMeta.sourceQuery, nextRequestMeta.sourceQuery); + + if (nextRequestMeta.applyGlobalQuery) { + updateDueToQuery = !_.isEqual(prevMeta.query, nextRequestMeta.query); + updateDueToFilters = !_.isEqual(prevMeta.filters, nextRequestMeta.filters); } } let updateDueToSearchSessionId = false; - if (timeAware || isQueryAware) { - updateDueToSearchSessionId = prevMeta.searchSessionId !== nextMeta.searchSessionId; + if ((timeAware || isQueryAware) && nextRequestMeta.applyForceRefresh) { + // If the force-refresh flag is turned off, we should ignore refreshes on the dashboard-context + updateDueToSearchSessionId = prevMeta.searchSessionId !== nextRequestMeta.searchSessionId; } let updateDueToPrecisionChange = false; let updateDueToExtentChange = false; if (isGeoGridPrecisionAware) { - updateDueToPrecisionChange = !_.isEqual(prevMeta.geogridPrecision, nextMeta.geogridPrecision); + updateDueToPrecisionChange = !_.isEqual( + prevMeta.geogridPrecision, + nextRequestMeta.geogridPrecision + ); } if (extentAware) { - updateDueToExtentChange = updateDueToExtent(prevMeta, nextMeta); + updateDueToExtentChange = updateDueToExtent(prevMeta, nextRequestMeta); } - const updateDueToSourceMetaChange = !_.isEqual(prevMeta.sourceMeta, nextMeta.sourceMeta); + const updateDueToSourceMetaChange = !_.isEqual(prevMeta.sourceMeta, nextRequestMeta.sourceMeta); return ( !updateDueToApplyGlobalTime && !updateDueToTime && !updateDueToTimeslice && - !updateDueToRefreshTimer && !updateDueToExtentChange && !updateDueToFields && !updateDueToQuery && @@ -173,7 +161,7 @@ export function canSkipStyleMetaUpdate({ nextMeta, }: { prevDataRequest: DataRequest | undefined; - nextMeta: DataMeta; + nextMeta: DataRequestMeta; }): boolean { if (!prevDataRequest) { return false; @@ -208,7 +196,7 @@ export function canSkipFormattersUpdate({ nextMeta, }: { prevDataRequest: DataRequest | undefined; - nextMeta: DataMeta; + nextMeta: DataRequestMeta; }): boolean { if (!prevDataRequest) { return false; diff --git a/x-pack/plugins/maps/public/classes/util/data_request.ts b/x-pack/plugins/maps/public/classes/util/data_request.ts index 0eb50af6107e0..3977fd3c9e0a9 100644 --- a/x-pack/plugins/maps/public/classes/util/data_request.ts +++ b/x-pack/plugins/maps/public/classes/util/data_request.ts @@ -7,7 +7,7 @@ /* eslint-disable max-classes-per-file */ -import { DataRequestDescriptor, DataMeta } from '../../../common/descriptor_types'; +import { DataRequestDescriptor, DataRequestMeta } from '../../../common/descriptor_types'; export class DataRequest { private readonly _descriptor: DataRequestDescriptor; @@ -26,11 +26,11 @@ export class DataRequest { return !!this._descriptor.dataRequestToken; } - getMeta(): DataMeta { - if (this._descriptor.dataMetaAtStart) { - return this._descriptor.dataMetaAtStart; - } else if (this._descriptor.dataMeta) { - return this._descriptor.dataMeta; + getMeta(): DataRequestMeta { + if (this._descriptor.dataRequestMetaAtStart) { + return this._descriptor.dataRequestMetaAtStart; + } else if (this._descriptor.dataRequestMeta) { + return this._descriptor.dataRequestMeta; } else { return {}; } diff --git a/x-pack/plugins/maps/public/classes/util/is_refresh_only_query.ts b/x-pack/plugins/maps/public/classes/util/is_refresh_only_query.ts deleted file mode 100644 index 57a11c1d161dc..0000000000000 --- a/x-pack/plugins/maps/public/classes/util/is_refresh_only_query.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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { MapQuery } from '../../../common/descriptor_types'; - -// Refresh only query is query where timestamps are different but query is the same. -// Triggered by clicking "Refresh" button in QueryBar -export function isRefreshOnlyQuery( - prevQuery: MapQuery | undefined, - newQuery: MapQuery | undefined -): boolean { - if (!prevQuery || !newQuery) { - return false; - } - return ( - prevQuery.queryLastTriggeredAt !== newQuery.queryLastTriggeredAt && - prevQuery.language === newQuery.language && - prevQuery.query === newQuery.query - ); -} diff --git a/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts b/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts index eb58963929716..68efd416718fd 100644 --- a/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts +++ b/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts @@ -15,7 +15,7 @@ import { import { Timeslice } from '../../../common/descriptor_types'; export interface TimesliceMaskConfig { - timesiceMaskField: string; + timesliceMaskField: string; timeslice: Timeslice; } @@ -34,15 +34,15 @@ function getFilterExpression( } if (timesliceMaskConfig) { - allFilters.push(['has', timesliceMaskConfig.timesiceMaskField]); + allFilters.push(['has', timesliceMaskConfig.timesliceMaskField]); allFilters.push([ '>=', - ['get', timesliceMaskConfig.timesiceMaskField], + ['get', timesliceMaskConfig.timesliceMaskField], timesliceMaskConfig.timeslice.from, ]); allFilters.push([ '<', - ['get', timesliceMaskConfig.timesiceMaskField], + ['get', timesliceMaskConfig.timesliceMaskField], timesliceMaskConfig.timeslice.to, ]); } diff --git a/x-pack/plugins/maps/public/components/force_refresh_checkbox.tsx b/x-pack/plugins/maps/public/components/force_refresh_checkbox.tsx new file mode 100644 index 0000000000000..1b0d021b2efdb --- /dev/null +++ b/x-pack/plugins/maps/public/components/force_refresh_checkbox.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFormRow, EuiSwitch, EuiSwitchEvent, EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +interface Props { + applyForceRefresh: boolean; + setApplyForceRefresh: (applyGlobalTime: boolean) => void; +} + +export function ForceRefreshCheckbox({ applyForceRefresh, setApplyForceRefresh }: Props) { + const onRespondToForceRefreshChange = (event: EuiSwitchEvent) => { + setApplyForceRefresh(event.target.checked); + }; + + return ( + + + + + + ); +} diff --git a/x-pack/plugins/maps/public/components/global_filter_checkbox.tsx b/x-pack/plugins/maps/public/components/global_filter_checkbox.tsx index bddb1cfd9cfcd..96805e0c6b5ec 100644 --- a/x-pack/plugins/maps/public/components/global_filter_checkbox.tsx +++ b/x-pack/plugins/maps/public/components/global_filter_checkbox.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { EuiFormRow, EuiSwitch, EuiSwitchEvent } from '@elastic/eui'; +import { EuiFormRow, EuiSwitch, EuiSwitchEvent, EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; interface Props { applyGlobalQuery: boolean; @@ -21,13 +22,20 @@ export function GlobalFilterCheckbox({ applyGlobalQuery, label, setApplyGlobalQu return ( - + + + ); } diff --git a/x-pack/plugins/maps/public/components/global_time_checkbox.tsx b/x-pack/plugins/maps/public/components/global_time_checkbox.tsx index 675426dbb3f76..ae0c50c063b68 100644 --- a/x-pack/plugins/maps/public/components/global_time_checkbox.tsx +++ b/x-pack/plugins/maps/public/components/global_time_checkbox.tsx @@ -6,8 +6,8 @@ */ import React from 'react'; -import { EuiFormRow, EuiSwitch, EuiSwitchEvent } from '@elastic/eui'; - +import { EuiFormRow, EuiSwitch, EuiSwitchEvent, EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; interface Props { applyGlobalTime: boolean; label: string; @@ -21,13 +21,20 @@ export function GlobalTimeCheckbox({ applyGlobalTime, label, setApplyGlobalTime return ( - + + + ); } diff --git a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/filter_editor/filter_editor.tsx b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/filter_editor/filter_editor.tsx index 6e258e679b96f..c92bd43af14cf 100644 --- a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/filter_editor/filter_editor.tsx +++ b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/filter_editor/filter_editor.tsx @@ -15,8 +15,10 @@ import { EuiSpacer, EuiText, EuiTextColor, - EuiTextAlign, EuiButtonEmpty, + EuiHorizontalRule, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -27,6 +29,7 @@ import { getIndexPatternService, getData } from '../../../kibana_services'; import { GlobalFilterCheckbox } from '../../../components/global_filter_checkbox'; import { GlobalTimeCheckbox } from '../../../components/global_time_checkbox'; import { ILayer } from '../../../classes/layers/layer'; +import { ForceRefreshCheckbox } from '../../../components/force_refresh_checkbox'; export interface Props { layer: ILayer; @@ -113,6 +116,10 @@ export class FilterEditor extends Component { this.props.updateSourceProp(this.props.layer.getId(), 'applyGlobalTime', applyGlobalTime); }; + _onRespondToForceRefreshChange = (applyForceRefresh: boolean) => { + this.props.updateSourceProp(this.props.layer.getId(), 'applyForceRefresh', applyForceRefresh); + }; + _renderQueryPopover() { const layerQuery = this.props.layer.getQuery(); const { SearchBar } = getData().ui; @@ -153,7 +160,7 @@ export class FilterEditor extends Component { const query = this.props.layer.getQuery(); if (!query || !query.query) { return ( - +

{ return ( {query.query} - ); @@ -183,7 +189,7 @@ export class FilterEditor extends Component { defaultMessage: 'Edit filter', }) : i18n.translate('xpack.maps.layerPanel.filterEditor.addFilterButtonLabel', { - defaultMessage: 'Add filter', + defaultMessage: 'Set filter', }); const openButtonIcon = query && query.query ? 'pencil' : 'plusInCircleFilled'; @@ -209,6 +215,7 @@ export class FilterEditor extends Component { setApplyGlobalTime={this._onApplyGlobalTimeChange} /> ) : null; + return ( @@ -222,12 +229,15 @@ export class FilterEditor extends Component { - {this._renderQuery()} - - {this._renderQueryPopover()} + + {this._renderQueryPopover()} + {this._renderQuery()} + + + { /> {globalTimeCheckbox} + ); } diff --git a/x-pack/plugins/maps/public/reducers/map/data_request_utils.test.ts b/x-pack/plugins/maps/public/reducers/map/data_request_utils.test.ts index d12af4bdddb53..abcdcd4ac99b3 100644 --- a/x-pack/plugins/maps/public/reducers/map/data_request_utils.test.ts +++ b/x-pack/plugins/maps/public/reducers/map/data_request_utils.test.ts @@ -7,7 +7,7 @@ jest.mock('../../actions', () => ({})); -import { DataMeta, DataRequestDescriptor } from '../../../common/descriptor_types'; +import { DataRequestMeta, DataRequestDescriptor } from '../../../common/descriptor_types'; import { getDataRequest, setDataRequest, @@ -157,7 +157,7 @@ describe('startDataRequest', () => { const REQUEST_TOKEN = Symbol('request'); const DATA_META_AT_START = { prop1: 'value', - } as DataMeta; + } as DataRequestMeta; test('Should return unmodified state if layer not found', () => { const state = ({ @@ -186,7 +186,7 @@ describe('startDataRequest', () => { __dataRequests: [ { dataId: 'source', - dataMetaAtStart: DATA_META_AT_START, + dataRequestMetaAtStart: DATA_META_AT_START, dataRequestToken: REQUEST_TOKEN, }, ], @@ -204,7 +204,7 @@ describe('startDataRequest', () => { __dataRequests: [ { dataId: 'source', - dataMetaAtStart: { prop1: 'old value' }, + dataRequestMetaAtStart: { prop1: 'old value' }, dataRequestToken: Symbol('request'), }, ], @@ -219,7 +219,7 @@ describe('startDataRequest', () => { __dataRequests: [ { dataId: 'source', - dataMetaAtStart: DATA_META_AT_START, + dataRequestMetaAtStart: DATA_META_AT_START, dataRequestToken: REQUEST_TOKEN, }, ], @@ -270,7 +270,7 @@ describe('stopDataRequest', () => { { dataId: 'source', dataRequestToken: REQUEST_TOKEN, - dataMetaAtStart: { requestProp1: 'request' }, + dataRequestMetaAtStart: { requestProp1: 'request' }, data: { prop1: 'old data ' }, }, ], @@ -278,7 +278,7 @@ describe('stopDataRequest', () => { ], } as unknown) as MapState; const stateClone = _.cloneDeep(state); - const reponseMeta = { responseProp1: 'response' } as DataMeta; + const reponseMeta = { responseProp1: 'response' } as DataRequestMeta; const data = { prop1: 'new data' }; expect(stopDataRequest(state, 'layer1', 'source', REQUEST_TOKEN, reponseMeta, data)).toEqual({ layerList: [ @@ -287,9 +287,9 @@ describe('stopDataRequest', () => { __dataRequests: [ { dataId: 'source', - dataMeta: { requestProp1: 'request', responseProp1: 'response' }, + dataRequestMeta: { requestProp1: 'request', responseProp1: 'response' }, data: { prop1: 'new data' }, - dataMetaAtStart: undefined, + dataRequestMetaAtStart: undefined, dataRequestToken: undefined, }, ], diff --git a/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts b/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts index 18a3fd3d6c150..ec97203deb520 100644 --- a/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts +++ b/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts @@ -7,7 +7,7 @@ import { SOURCE_DATA_REQUEST_ID } from '../../../common/constants'; import { findLayerById, setLayer } from './layer_utils'; -import { DataMeta, DataRequestDescriptor } from '../../../common/descriptor_types'; +import { DataRequestMeta, DataRequestDescriptor } from '../../../common/descriptor_types'; import { MapState } from './types'; export function startDataRequest( @@ -15,7 +15,7 @@ export function startDataRequest( layerId: string, dataRequestId: string, requestToken: symbol, - requestMeta: DataMeta + requestMeta: DataRequestMeta ): MapState { const layerDescriptor = findLayerById(state, layerId); if (!layerDescriptor) { @@ -30,7 +30,7 @@ export function startDataRequest( : { dataId: dataRequestId, }; - dataRequest.dataMetaAtStart = requestMeta; + dataRequest.dataRequestMetaAtStart = requestMeta; dataRequest.dataRequestToken = requestToken; return setDataRequest(state, layerId, dataRequest); } @@ -49,7 +49,7 @@ export function stopDataRequest( layerId: string, dataRequestId: string, requestToken: symbol, - responseMeta?: DataMeta, + responseMeta?: DataRequestMeta, data?: object ): MapState { const dataRequest = getDataRequest(state, layerId, dataRequestId, requestToken); @@ -57,11 +57,11 @@ export function stopDataRequest( ? setDataRequest(state, layerId, { ...dataRequest, data, - dataMeta: { - ...(dataRequest.dataMetaAtStart ? dataRequest.dataMetaAtStart : {}), + dataRequestMeta: { + ...(dataRequest.dataRequestMetaAtStart ? dataRequest.dataRequestMetaAtStart : {}), ...(responseMeta ? responseMeta : {}), }, - dataMetaAtStart: undefined, + dataRequestMetaAtStart: undefined, dataRequestToken: undefined, }) : state; diff --git a/x-pack/plugins/maps/public/reducers/map/map.ts b/x-pack/plugins/maps/public/reducers/map/map.ts index 30db4ef8120ad..511d7ef8efb7c 100644 --- a/x-pack/plugins/maps/public/reducers/map/map.ts +++ b/x-pack/plugins/maps/public/reducers/map/map.ts @@ -75,7 +75,6 @@ export const DEFAULT_MAP_STATE: MapState = { timeslice: undefined, query: undefined, filters: [], - refreshTimerLastTriggeredAt: undefined, drawState: undefined, editState: undefined, }, diff --git a/x-pack/plugins/maps/public/reducers/map/types.ts b/x-pack/plugins/maps/public/reducers/map/types.ts index b13ea9c13c230..9b4261b18f915 100644 --- a/x-pack/plugins/maps/public/reducers/map/types.ts +++ b/x-pack/plugins/maps/public/reducers/map/types.ts @@ -7,6 +7,7 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ +import type { Query } from 'src/plugins/data/common'; import { DrawState, EditState, @@ -14,7 +15,6 @@ import { LayerDescriptor, MapCenter, MapExtent, - MapQuery, Timeslice, TooltipState, } from '../../../common/descriptor_types'; @@ -39,9 +39,8 @@ export type MapContext = Partial & { }; timeFilters?: TimeRange; timeslice?: Timeslice; - query?: MapQuery; + query?: Query; filters: Filter[]; - refreshTimerLastTriggeredAt?: string; drawState?: DrawState; editState?: EditState; searchSessionId?: string; diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 4a2b0fbefad68..212fa89e2ad65 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -12,6 +12,7 @@ import { i18n } from '@kbn/i18n'; import { AppLeaveAction, AppMountParameters } from 'kibana/public'; import { Adapters } from 'src/plugins/embeddable/public'; import { Subscription } from 'rxjs'; +import type { Query, Filter, TimeRange, IndexPattern } from 'src/plugins/data/common'; import { getData, getCoreChrome, @@ -30,10 +31,6 @@ import { } from '../url_state'; import { esFilters, - Filter, - Query, - TimeRange, - IndexPattern, SavedQuery, QueryStateChange, QueryState, @@ -41,7 +38,6 @@ import { import { MapContainer } from '../../../connected_components/map_container'; import { getIndexPatternsFromIds } from '../../../index_pattern_util'; import { getTopNavConfig } from '../top_nav_config'; -import { MapQuery } from '../../../../common/descriptor_types'; import { goToSpecifiedPath } from '../../../render_app'; import { MapSavedObjectAttributes } from '../../../../common/map_saved_object_type'; import { getFullPath, APP_ID } from '../../../../common/constants'; @@ -87,7 +83,7 @@ export interface Props { }) => void; timeFilters: TimeRange; isSaveDisabled: boolean; - query: MapQuery | undefined; + query: Query | undefined; setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; } diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts index 45d3e0352acf6..fab88af308f8d 100644 --- a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts +++ b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts @@ -402,7 +402,7 @@ export class SavedMap { isPaused: getTimeFilter().getRefreshInterval().pause, interval: getTimeFilter().getRefreshInterval().value, }, - query: _.omit(getQuery(state), 'queryLastTriggeredAt'), + query: getQuery(state), filters: getFilters(state), settings: getMapSettings(state), }); diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts index a1b8ad97acb9f..9fc17b810964b 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.test.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.test.ts @@ -58,7 +58,6 @@ describe('getDataFilters', () => { const mapZoom = 4; const timeFilters = { to: '2001-01-01', from: '2001-12-31' }; const timeslice = undefined; - const refreshTimerLastTriggeredAt = '2001-01-01T00:00:00'; const query = undefined; const filters: Filter[] = []; const searchSessionId = '12345'; @@ -77,7 +76,6 @@ describe('getDataFilters', () => { mapZoom, timeFilters, timeslice, - refreshTimerLastTriggeredAt, query, filters, searchSessionId, @@ -94,7 +92,6 @@ describe('getDataFilters', () => { mapZoom, timeFilters, timeslice, - refreshTimerLastTriggeredAt, query, filters, searchSessionId, diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index 609b830f2f512..5ca297bdff020 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -9,6 +9,7 @@ import { createSelector } from 'reselect'; import { FeatureCollection } from 'geojson'; import _ from 'lodash'; import { Adapters } from 'src/plugins/inspector/public'; +import type { Query } from 'src/plugins/data/common'; import { TileLayer } from '../classes/layers/tile_layer/tile_layer'; // @ts-ignore import { VectorTileLayer } from '../classes/layers/vector_tile_layer/vector_tile_layer'; @@ -45,7 +46,6 @@ import { LayerDescriptor, MapCenter, MapExtent, - MapQuery, TooltipState, VectorLayerDescriptor, } from '../../common/descriptor_types'; @@ -179,7 +179,7 @@ export const getTimeFilters = ({ map }: MapStoreState): TimeRange => export const getTimeslice = ({ map }: MapStoreState) => map.mapState.timeslice; -export const getQuery = ({ map }: MapStoreState): MapQuery | undefined => map.mapState.query; +export const getQuery = ({ map }: MapStoreState): Query | undefined => map.mapState.query; export const getFilters = ({ map }: MapStoreState): Filter[] => map.mapState.filters; @@ -201,9 +201,6 @@ export const getDrawState = ({ map }: MapStoreState): DrawState | undefined => export const getEditState = ({ map }: MapStoreState): EditState | undefined => map.mapState.editState; -export const getRefreshTimerLastTriggeredAt = ({ map }: MapStoreState): string | undefined => - map.mapState.refreshTimerLastTriggeredAt; - function getLayerDescriptor(state: MapStoreState, layerId: string) { const layerListRaw = getLayerListRaw(state); return layerListRaw.find((layer) => layer.id === layerId); @@ -225,7 +222,6 @@ export const getDataFilters = createSelector( getMapZoom, getTimeFilters, getTimeslice, - getRefreshTimerLastTriggeredAt, getQuery, getFilters, getSearchSessionId, @@ -237,7 +233,6 @@ export const getDataFilters = createSelector( mapZoom, timeFilters, timeslice, - refreshTimerLastTriggeredAt, query, filters, searchSessionId, @@ -250,7 +245,6 @@ export const getDataFilters = createSelector( zoom: mapZoom, timeFilters, timeslice, - refreshTimerLastTriggeredAt, query, filters, searchSessionId, From 5e2511fc4335470cd86f7a433435fb37b5c92dbf Mon Sep 17 00:00:00 2001 From: Madison Caldwell Date: Thu, 9 Sep 2021 13:38:20 -0400 Subject: [PATCH 17/32] [RAC][Security Solution] Add RAC support to rule routes (#108053) * prototyping * how dis * RAC rules create API * Find rules (in progress) * Finalize find_rules route * A couple more routes, and type error fixes * Fix integration tests? * Fix tests * Fix imports * Add ref * Test fixes * Fix refs * Type fixes * Test fixes * Remove console log * Update rule changes * Test and type fixes * Fix patch rule tests * Fix types * Begin removing namespace as required param * Remove generics * Support RAC everywhere * Tests passing * Types * Keep on passing isRuleRegistryEnabled around * Rewrite install_prepackaged_timelines helper tests --- x-pack/plugins/rule_registry/server/index.ts | 3 + .../security_solution/common/constants.ts | 19 ++- .../schemas/common/schemas.ts | 6 + ...s => add_prepackaged_rules_schema.test.ts} | 17 +++ .../request/add_prepackaged_rules_schema.ts | 5 +- .../schemas/request/rule_schemas.test.ts | 13 ++ .../schemas/request/rule_schemas.ts | 2 + .../request/update_rules_bulk_schema.test.ts | 12 ++ .../schemas/response/rules_schema.test.ts | 13 ++ .../schemas/response/rules_schema.ts | 2 + ...dule_throttle_notification_actions.test.ts | 1 + .../routes/__mocks__/request_responses.ts | 20 +-- .../rules/add_prepackaged_rules_route.test.ts | 57 +++++---- .../rules/add_prepackaged_rules_route.ts | 29 +++-- .../rules/create_rules_bulk_route.test.ts | 41 +++--- .../routes/rules/create_rules_bulk_route.ts | 19 ++- .../routes/rules/create_rules_route.test.ts | 36 +++--- .../routes/rules/create_rules_route.ts | 20 ++- .../rules/delete_rules_bulk_route.test.ts | 9 +- .../routes/rules/delete_rules_bulk_route.ts | 15 ++- .../routes/rules/delete_rules_route.test.ts | 13 +- .../routes/rules/delete_rules_route.ts | 7 +- .../routes/rules/export_rules_route.ts | 15 ++- .../routes/rules/find_rules_route.test.ts | 13 +- .../routes/rules/find_rules_route.ts | 4 +- .../rules/find_rules_status_route.test.ts | 11 +- ...get_prepackaged_rules_status_route.test.ts | 21 +++- .../get_prepackaged_rules_status_route.ts | 9 +- .../routes/rules/import_rules_route.test.ts | 47 ++++--- .../routes/rules/import_rules_route.ts | 7 +- .../rules/patch_rules_bulk_route.test.ts | 13 +- .../routes/rules/patch_rules_bulk_route.ts | 12 +- .../routes/rules/patch_rules_route.test.ts | 19 ++- .../routes/rules/patch_rules_route.ts | 16 ++- .../rules/perform_bulk_action_route.test.ts | 9 +- .../routes/rules/perform_bulk_action_route.ts | 7 +- .../routes/rules/read_rules_route.test.ts | 11 +- .../routes/rules/read_rules_route.ts | 8 +- .../rules/update_rules_bulk_route.test.ts | 13 +- .../routes/rules/update_rules_bulk_route.ts | 6 +- .../routes/rules/update_rules_route.test.ts | 19 ++- .../routes/rules/update_rules_route.ts | 14 ++- .../routes/rules/utils.test.ts | 118 +++++++++++------- .../detection_engine/routes/rules/utils.ts | 15 ++- .../routes/rules/validate.test.ts | 49 ++++++-- .../detection_engine/routes/rules/validate.ts | 15 ++- .../routes/tags/read_tags_route.ts | 6 +- .../lib/detection_engine/routes/utils.test.ts | 9 +- .../lib/detection_engine/routes/utils.ts | 2 +- .../create_indicator_match_alert_type.ts | 4 +- .../lib/detection_engine/rule_types/ml.ts | 4 +- .../rule_types/ml/create_ml_alert_type.ts | 4 +- .../query/create_query_alert_type.ts | 4 +- .../rules/create_rules.mock.ts | 8 +- .../rules/create_rules.test.ts | 9 +- .../detection_engine/rules/create_rules.ts | 6 +- .../rules/duplicate_rule.test.ts | 2 + .../detection_engine/rules/find_rules.test.ts | 40 ++++-- .../lib/detection_engine/rules/find_rules.ts | 19 ++- .../get_existing_prepackaged_rules.test.ts | 59 ++++----- .../rules/get_existing_prepackaged_rules.ts | 22 +++- .../rules/get_export_all.test.ts | 13 +- .../detection_engine/rules/get_export_all.ts | 5 +- .../rules/get_export_by_object_ids.test.ts | 25 ++-- .../rules/get_export_by_object_ids.ts | 11 +- .../rules/get_rules_to_install.test.ts | 28 +++-- .../rules/get_rules_to_install.ts | 2 +- .../rules/get_rules_to_update.test.ts | 53 ++++---- .../rules/get_rules_to_update.ts | 2 +- .../rules/install_prepacked_rules.ts | 6 +- .../rules/patch_rules.mock.ts | 8 +- .../rules/patch_rules.test.ts | 29 +++-- .../lib/detection_engine/rules/patch_rules.ts | 3 + .../detection_engine/rules/read_rules.test.ts | 37 ++++-- .../lib/detection_engine/rules/read_rules.ts | 9 +- .../lib/detection_engine/rules/types.ts | 17 ++- .../rules/update_prepacked_rules.test.ts | 10 +- .../rules/update_prepacked_rules.ts | 16 ++- .../rules/update_rules.mock.ts | 7 +- .../rules/update_rules.test.ts | 23 ++-- .../detection_engine/rules/update_rules.ts | 7 +- .../lib/detection_engine/rules/utils.test.ts | 3 + .../lib/detection_engine/rules/utils.ts | 2 + .../schemas/rule_converters.ts | 8 +- .../schemas/rule_schemas.mock.ts | 1 + .../detection_engine/schemas/rule_schemas.ts | 23 +++- .../signals/search_after_bulk_create.ts | 2 +- .../signals/signal_rule_alert_type.test.ts | 16 +-- .../lib/detection_engine/signals/utils.ts | 18 +++ .../detection_engine/tags/read_tags.test.ts | 81 ++++++------ .../lib/detection_engine/tags/read_tags.ts | 8 +- .../helpers.test.ts | 59 ++++----- .../security_solution/server/plugin.ts | 10 +- .../security_solution/server/routes/index.ts | 42 +++---- 94 files changed, 1063 insertions(+), 549 deletions(-) rename x-pack/plugins/security_solution/common/detection_engine/schemas/request/{add_prepackged_rules_schema.test.ts => add_prepackaged_rules_schema.test.ts} (98%) diff --git a/x-pack/plugins/rule_registry/server/index.ts b/x-pack/plugins/rule_registry/server/index.ts index 33822da746cd2..b287e6a3e4688 100644 --- a/x-pack/plugins/rule_registry/server/index.ts +++ b/x-pack/plugins/rule_registry/server/index.ts @@ -12,6 +12,9 @@ import { PluginInitializerContext } from 'src/core/server'; import { RuleRegistryPlugin } from './plugin'; export type { RuleRegistryPluginSetupContract, RuleRegistryPluginStartContract } from './plugin'; +export { RuleDataPluginService } from './rule_data_plugin_service'; +export { RuleDataClient } from './rule_data_client'; +export { IRuleDataClient } from './rule_data_client/types'; export type { RacRequestHandlerContext, RacApiRequestHandlerContext, diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index e80dd9ab8bf31..8076caf60f697 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -187,19 +187,18 @@ export const DEFAULT_TRANSFORMS_SETTING = JSON.stringify(defaultTransformsSettin /** * Id for the signals alerting type */ -export const SIGNALS_ID = `siem.signals`; +export const SIGNALS_ID = `siem.signals` as const; /** - * Id's for reference rule types + * IDs for RAC rule types */ -export const REFERENCE_RULE_ALERT_TYPE_ID = `siem.referenceRule`; -export const REFERENCE_RULE_PERSISTENCE_ALERT_TYPE_ID = `siem.referenceRulePersistence`; - -export const QUERY_ALERT_TYPE_ID = `siem.queryRule`; -export const EQL_ALERT_TYPE_ID = `siem.eqlRule`; -export const INDICATOR_ALERT_TYPE_ID = `siem.indicatorRule`; -export const ML_ALERT_TYPE_ID = `siem.mlRule`; -export const THRESHOLD_ALERT_TYPE_ID = `siem.thresholdRule`; +const RULE_TYPE_PREFIX = `siem` as const; +export const EQL_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.eqlRule` as const; +export const INDICATOR_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.indicatorRule` as const; +export const ML_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.mlRule` as const; +export const QUERY_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.queryRule` as const; +export const SAVED_QUERY_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.savedQueryRule` as const; +export const THRESHOLD_RULE_TYPE_ID = `${RULE_TYPE_PREFIX}.thresholdRule` as const; /** * Id for the notifications alerting type diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts index ab89ab31acc02..a9f7d96f1eb2e 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts @@ -59,6 +59,9 @@ export type FileName = t.TypeOf; export const exclude_export_details = t.boolean; export type ExcludeExportDetails = t.TypeOf; +export const namespace = t.string; +export type Namespace = t.TypeOf; + /** * TODO: Right now the filters is an "unknown", when it could more than likely * become the actual ESFilter as a type. @@ -352,6 +355,9 @@ export const timelines_not_updated = PositiveInteger; export const note = t.string; export type Note = t.TypeOf; +export const namespaceOrUndefined = t.union([namespace, t.undefined]); +export type NamespaceOrUndefined = t.TypeOf; + export const noteOrUndefined = t.union([note, t.undefined]); export type NoteOrUndefined = t.TypeOf; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackged_rules_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackaged_rules_schema.test.ts similarity index 98% rename from x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackged_rules_schema.test.ts rename to x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackaged_rules_schema.test.ts index 03c0947aaf50c..7e34dd4a1efc0 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackged_rules_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackaged_rules_schema.test.ts @@ -465,6 +465,23 @@ describe('add prepackaged rules schema', () => { expect(message.schema).toEqual(expected); }); + test('You can send in a namespace', () => { + const payload: AddPrepackagedRulesSchema = { + ...getAddPrepackagedRulesSchemaMock(), + namespace: 'a namespace', + }; + + const decoded = addPrepackagedRulesSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + const expected: AddPrepackagedRulesSchemaDecoded = { + ...getAddPrepackagedRulesSchemaDecodedMock(), + namespace: 'a namespace', + }; + expect(message.schema).toEqual(expected); + }); + test('You can send in an empty array to threat', () => { const payload: AddPrepackagedRulesSchema = { ...getAddPrepackagedRulesSchemaMock(), diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackaged_rules_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackaged_rules_schema.ts index eed20951190b7..618aee3379316 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackaged_rules_schema.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/add_prepackaged_rules_schema.ts @@ -71,6 +71,7 @@ import { timestamp_override, Author, event_category_override, + namespace, } from '../common/schemas'; /** @@ -136,10 +137,10 @@ export const addPrepackagedRulesSchema = t.intersection([ threat_indicator_path, // defaults "undefined" if not set during decode concurrent_searches, // defaults to "undefined" if not set during decode items_per_search, // defaults to "undefined" if not set during decode + namespace, // defaults to "undefined" if not set during decode }) ), ]); - export type AddPrepackagedRulesSchema = t.TypeOf; // This type is used after a decode since some things are defaults after a decode. @@ -153,6 +154,7 @@ export type AddPrepackagedRulesSchemaDecoded = Omit< | 'from' | 'interval' | 'max_signals' + | 'namespace' | 'risk_score_mapping' | 'severity_mapping' | 'tags' @@ -176,4 +178,5 @@ export type AddPrepackagedRulesSchemaDecoded = Omit< threat: Threats; throttle: ThrottleOrNull; exceptions_list: ListArray; + namespace?: string; }; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.test.ts index 2e4a53766448b..72334c81ce077 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.test.ts @@ -330,6 +330,19 @@ describe('create rules schema', () => { expect(message.schema).toEqual(payload); }); + test('You can send in a namespace', () => { + const payload: CreateRulesSchema = { + ...getCreateRulesSchemaMock(), + namespace: 'a namespace', + }; + + const decoded = createRulesSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + test('You can send in an empty array to threat', () => { const payload: CreateRulesSchema = { ...getCreateRulesSchemaMock(), diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts index b1361d8513c65..719337a231c1c 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts @@ -68,6 +68,7 @@ import { last_success_message, last_failure_at, last_failure_message, + namespace, } from '../common/schemas'; export const createSchema = < @@ -155,6 +156,7 @@ const baseParams = { meta, rule_name_override, timestamp_override, + namespace, }, defaultable: { tags, diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts index 63217186affe7..c5549913eb05c 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts @@ -187,6 +187,18 @@ describe('update_rules_bulk_schema', () => { expect(output.schema).toEqual({}); }); + test('You can set "namespace" to a string', () => { + const payload: UpdateRulesBulkSchema = [ + { ...getUpdateRulesSchemaMock(), namespace: 'a namespace' }, + ]; + + const decoded = updateRulesBulkSchema.decode(payload); + const checked = exactCheck(payload, decoded); + const output = foldLeftRight(checked); + expect(formatErrors(output.errors)).toEqual([]); + expect(output.schema).toEqual(payload); + }); + test('You can set "note" to a string', () => { const payload: UpdateRulesBulkSchema = [ { ...getUpdateRulesSchemaMock(), note: '# test markdown' }, diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts index ef18cf24e87a3..f8404ac677186 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts @@ -404,6 +404,19 @@ describe('rules_schema', () => { expect(message.schema).toEqual(expected); }); + test('it should validate a namespace as string', () => { + const payload = { + ...getRulesSchemaMock(), + namespace: 'a namespace', + }; + const dependents = getDependents(payload); + const decoded = dependents.decode(payload); + const checked = exactCheck(payload, decoded); + const message = pipe(checked, foldLeftRight); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); + }); + test('it should NOT validate invalid_data for the type', () => { const payload: Omit & { type: string } = getRulesSchemaMock(); payload.type = 'invalid_data'; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts index 0efd6dc5067cb..da13faae8a47c 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts @@ -75,6 +75,7 @@ import { license, rule_name_override, timestamp_override, + namespace, } from '../common/schemas'; import { typeAndTimelineOnlySchema, TypeAndTimelineOnly } from './type_timeline_only_schema'; @@ -174,6 +175,7 @@ export const partialRulesSchema = t.partial({ filters, meta, index, + namespace, note, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_throttle_notification_actions.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_throttle_notification_actions.test.ts index de62c6b211400..2e5e331b71b00 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_throttle_notification_actions.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_throttle_notification_actions.test.ts @@ -53,6 +53,7 @@ describe('schedule_throttle_notification_actions', () => { to: 'now', type: 'query', references: ['http://www.example.com'], + namespace: 'a namespace', note: '# sample markdown', version: 1, exceptionsList: [], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts index a7eff049d0d9e..97d976d337564 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -39,6 +39,7 @@ import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; import { getPerformBulkActionSchemaMock } from '../../../../../common/detection_engine/schemas/request/perform_bulk_action_schema.mock'; import { RuleExecutionStatus } from '../../../../../common/detection_engine/schemas/common/schemas'; import { FindBulkExecutionLogResponse } from '../../rule_execution_log/types'; +import { ruleTypeMappings } from '../../signals/utils'; export const typicalSetStatusSignalByIdsPayload = (): SetSignalsStatusSchemaDecoded => ({ signal_ids: ['somefakeid1', 'somefakeid2'], @@ -179,18 +180,18 @@ export const getEmptyFindResult = (): FindHit => ({ data: [], }); -export const getFindResultWithSingleHit = (): FindHit => ({ +export const getFindResultWithSingleHit = (isRuleRegistryEnabled: boolean): FindHit => ({ page: 1, perPage: 1, total: 1, - data: [getAlertMock(getQueryRuleParams())], + data: [getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())], }); -export const nonRuleFindResult = (): FindHit => ({ +export const nonRuleFindResult = (isRuleRegistryEnabled: boolean): FindHit => ({ page: 1, perPage: 1, total: 1, - data: [nonRuleAlert()], + data: [nonRuleAlert(isRuleRegistryEnabled)], }); export const getFindResultWithMultiHits = ({ @@ -348,19 +349,22 @@ export const createActionResult = (): ActionResult => ({ isPreconfigured: false, }); -export const nonRuleAlert = () => ({ +export const nonRuleAlert = (isRuleRegistryEnabled: boolean) => ({ // Defaulting to QueryRuleParams because ts doesn't like empty objects - ...getAlertMock(getQueryRuleParams()), + ...getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), id: '04128c15-0d1b-4716-a4c5-46997ac7f3bc', name: 'Non-Rule Alert', alertTypeId: 'something', }); -export const getAlertMock = (params: T): Alert => ({ +export const getAlertMock = ( + isRuleRegistryEnabled: boolean, + params: T +): Alert => ({ id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', name: 'Detect Root/Admin Users', tags: [`${INTERNAL_RULE_ID_KEY}:rule-1`, `${INTERNAL_IMMUTABLE_KEY}:false`], - alertTypeId: 'siem.signals', + alertTypeId: isRuleRegistryEnabled ? ruleTypeMappings[params.type] : 'siem.signals', consumer: 'siem', params, createdAt: new Date('2019-12-13T16:40:33.400Z'), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts index 189173f44a295..866c70626d2bc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts @@ -72,12 +72,16 @@ jest.mock('../../../timeline/routes/prepackaged_timelines/install_prepackaged_ti }; }); -describe('add_prepackaged_rules_route', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('add_prepackaged_rules_route - %s', (_, isRuleRegistryEnabled) => { const siemMockClient = siemMock.createClient(); let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let securitySetup: SecurityPluginSetup; let mockExceptionsClient: ExceptionListClient; + const testif = isRuleRegistryEnabled ? test.skip : test; beforeEach(() => { server = serverMock.create(); @@ -91,8 +95,10 @@ describe('add_prepackaged_rules_route', () => { mockExceptionsClient = listMock.getExceptionListClient(); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - clients.rulesClient.update.mockResolvedValue(getAlertMock(getQueryRuleParams())); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + clients.rulesClient.update.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); (installPrepackagedTimelines as jest.Mock).mockReset(); (installPrepackagedTimelines as jest.Mock).mockResolvedValue({ @@ -106,7 +112,7 @@ describe('add_prepackaged_rules_route', () => { context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 1 } }) ); - addPrepackedRulesRoute(server.router, createMockConfig(), securitySetup); + addPrepackedRulesRoute(server.router, createMockConfig(), securitySetup, isRuleRegistryEnabled); }); describe('status codes', () => { @@ -129,23 +135,25 @@ describe('add_prepackaged_rules_route', () => { }); }); - test('it returns a 400 if the index does not exist', async () => { + test('it returns a 400 if the index does not exist when rule registry not enabled', async () => { const request = addPrepackagedRulesRequest(); context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 0 } }) ); const response = await server.inject(request, context); - expect(response.status).toEqual(400); - expect(response.body).toEqual({ - status_code: 400, - message: expect.stringContaining( - 'Pre-packaged rules cannot be installed until the signals index is created' - ), - }); + expect(response.status).toEqual(isRuleRegistryEnabled ? 200 : 400); + if (!isRuleRegistryEnabled) { + expect(response.body).toEqual({ + status_code: 400, + message: expect.stringContaining( + 'Pre-packaged rules cannot be installed until the signals index is created' + ), + }); + } }); - it('returns 404 if siem client is unavailable', async () => { + test('returns 404 if siem client is unavailable', async () => { const { securitySolution, ...contextWithoutSecuritySolution } = context; const response = await server.inject( addPrepackagedRulesRequest(), @@ -185,16 +193,19 @@ describe('add_prepackaged_rules_route', () => { }); }); - test('catches errors if payloads cause errors to be thrown', async () => { - context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( - elasticsearchClientMock.createErrorTransportRequestPromise(new Error('Test error')) - ); - const request = addPrepackagedRulesRequest(); - const response = await server.inject(request, context); - - expect(response.status).toEqual(500); - expect(response.body).toEqual({ message: 'Test error', status_code: 500 }); - }); + testif( + 'catches errors if signals index does not exist when rule registry not enabled', + async () => { + context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( + elasticsearchClientMock.createErrorTransportRequestPromise(new Error('Test error')) + ); + const request = addPrepackagedRulesRequest(); + const response = await server.inject(request, context); + + expect(response.status).toEqual(500); + expect(response.body).toEqual({ message: 'Test error', status_code: 500 }); + } + ); }); test('should install prepackaged timelines', async () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts index 21933b2918722..0048c735b0a7c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.ts @@ -43,7 +43,8 @@ import { installPrepackagedTimelines } from '../../../timeline/routes/prepackage export const addPrepackedRulesRoute = ( router: SecuritySolutionPluginRouter, config: ConfigType, - security: SetupPlugins['security'] + security: SetupPlugins['security'], + isRuleRegistryEnabled: boolean ) => { router.put( { @@ -79,7 +80,9 @@ export const addPrepackedRulesRoute = ( frameworkRequest, config.maxTimelineImportExportSize, config.prebuiltRulesFromFileSystem, - config.prebuiltRulesFromSavedObjects + config.prebuiltRulesFromSavedObjects, + undefined, + isRuleRegistryEnabled ); return response.ok({ body: validated ?? {} }); } catch (err) { @@ -109,7 +112,8 @@ export const createPrepackagedRules = async ( maxTimelineImportExportSize: ConfigType['maxTimelineImportExportSize'], prebuiltRulesFromFileSystem: ConfigType['prebuiltRulesFromFileSystem'], prebuiltRulesFromSavedObjects: ConfigType['prebuiltRulesFromSavedObjects'], - exceptionsClient?: ExceptionListClient + exceptionsClient?: ExceptionListClient, + isRuleRegistryEnabled?: boolean | undefined ): Promise => { const esClient = context.core.elasticsearch.client; const savedObjectsClient = context.core.savedObjects.client; @@ -131,11 +135,14 @@ export const createPrepackagedRules = async ( prebuiltRulesFromFileSystem, prebuiltRulesFromSavedObjects ); - const prepackagedRules = await getExistingPrepackagedRules({ rulesClient }); + const prepackagedRules = await getExistingPrepackagedRules({ + rulesClient, + isRuleRegistryEnabled: isRuleRegistryEnabled ?? false, + }); const rulesToInstall = getRulesToInstall(latestPrepackagedRules, prepackagedRules); const rulesToUpdate = getRulesToUpdate(latestPrepackagedRules, prepackagedRules); const signalsIndex = siemClient.getSignalsIndex(); - if (rulesToInstall.length !== 0 || rulesToUpdate.length !== 0) { + if (!isRuleRegistryEnabled && (rulesToInstall.length !== 0 || rulesToUpdate.length !== 0)) { const signalsIndexExists = await getIndexExists(esClient.asCurrentUser, signalsIndex); if (!signalsIndexExists) { throw new PrepackagedRulesError( @@ -145,7 +152,14 @@ export const createPrepackagedRules = async ( } } - await Promise.all(installPrepackagedRules(rulesClient, rulesToInstall, signalsIndex)); + await Promise.all( + installPrepackagedRules( + rulesClient, + rulesToInstall, + signalsIndex, + isRuleRegistryEnabled ?? false + ) + ); const timeline = await installPrepackagedTimelines( maxTimelineImportExportSize, frameworkRequest, @@ -160,7 +174,8 @@ export const createPrepackagedRules = async ( context.securitySolution.getSpaceId(), ruleStatusClient, rulesToUpdate, - signalsIndex + signalsIndex, + isRuleRegistryEnabled ?? false ); const prepackagedRulesOutput: PrePackagedRulesAndTimelinesSchema = { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index 3de2770972c82..2c8696dbd4554 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -24,7 +24,10 @@ import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('create_rules_bulk', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('create_rules_bulk - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -35,12 +38,14 @@ describe('create_rules_bulk', () => { ml = mlServicesMock.createSetupContract(); clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); // no existing rules - clients.rulesClient.create.mockResolvedValue(getAlertMock(getQueryRuleParams())); // successful creation + clients.rulesClient.create.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); // successful creation context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 1 } }) ); - createRulesBulkRoute(server.router, ml); + createRulesBulkRoute(server.router, ml, isRuleRegistryEnabled); }); describe('status codes', () => { @@ -56,7 +61,7 @@ describe('create_rules_bulk', () => { expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); }); - it('returns 404 if siem client is unavailable', async () => { + test('returns 404 if siem client is unavailable', async () => { const { securitySolution, ...contextWithoutSecuritySolution } = context; // @ts-expect-error const response = await server.inject(getReadBulkRequest(), contextWithoutSecuritySolution); @@ -66,7 +71,7 @@ describe('create_rules_bulk', () => { }); describe('unhappy paths', () => { - it('returns a 403 error object if ML Authz fails', async () => { + test('returns a 403 error object if ML Authz fails', async () => { (buildMlAuthz as jest.Mock).mockReturnValueOnce({ validateRuleType: jest .fn() @@ -86,26 +91,30 @@ describe('create_rules_bulk', () => { ]); }); - it('returns an error object if the index does not exist', async () => { + test('returns an error object if the index does not exist when rule registry not enabled', async () => { context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 0 } }) ); const response = await server.inject(getReadBulkRequest(), context); expect(response.status).toEqual(200); - expect(response.body).toEqual([ - { - error: { - message: 'To create a rule, the index must exist first. Index undefined does not exist', - status_code: 400, + + if (!isRuleRegistryEnabled) { + expect(response.body).toEqual([ + { + error: { + message: + 'To create a rule, the index must exist first. Index undefined does not exist', + status_code: 400, + }, + rule_id: 'rule-1', }, - rule_id: 'rule-1', - }, - ]); + ]); + } }); test('returns a duplicate error if rule_id already exists', async () => { - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const response = await server.inject(getReadBulkRequest(), context); expect(response.status).toEqual(200); @@ -136,7 +145,7 @@ describe('create_rules_bulk', () => { ]); }); - it('returns an error object if duplicate rule_ids found in request payload', async () => { + test('returns an error object if duplicate rule_ids found in request payload', async () => { const request = requestMock.create({ method: 'post', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts index 5f44ab0ada92d..31683c289d4b4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.ts @@ -28,7 +28,8 @@ import { convertCreateAPIToInternalSchema } from '../../schemas/rule_converters' export const createRulesBulkRoute = ( router: SecuritySolutionPluginRouter, - ml: SetupPlugins['ml'] + ml: SetupPlugins['ml'], + isRuleRegistryEnabled: boolean ) => { router.post( { @@ -67,9 +68,10 @@ export const createRulesBulkRoute = ( .map(async (payloadRule) => { if (payloadRule.rule_id != null) { const rule = await readRules({ + id: undefined, + isRuleRegistryEnabled, rulesClient, ruleId: payloadRule.rule_id, - id: undefined, }); if (rule != null) { return createBulkErrorObject({ @@ -79,7 +81,11 @@ export const createRulesBulkRoute = ( }); } } - const internalRule = convertCreateAPIToInternalSchema(payloadRule, siemClient); + const internalRule = convertCreateAPIToInternalSchema( + payloadRule, + siemClient, + isRuleRegistryEnabled + ); try { const validationErrors = createRuleValidateTypeDependents(payloadRule); if (validationErrors.length) { @@ -93,7 +99,7 @@ export const createRulesBulkRoute = ( throwHttpError(await mlAuthz.validateRuleType(internalRule.params.type)); const finalIndex = internalRule.params.outputIndex; const indexExists = await getIndexExists(esClient.asCurrentUser, finalIndex); - if (!indexExists) { + if (!isRuleRegistryEnabled && !indexExists) { return createBulkErrorObject({ ruleId: internalRule.params.ruleId, statusCode: 400, @@ -112,7 +118,10 @@ export const createRulesBulkRoute = ( return transformValidateBulkError(internalRule.params.ruleId, createdRule, undefined); } catch (err) { - return transformBulkError(internalRule.params.ruleId, err); + return transformBulkError( + internalRule.params.ruleId, + err as Error & { statusCode?: number | undefined } + ); } }) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts index fc48e34a7ca74..d1be96a44930a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts @@ -24,7 +24,10 @@ import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mo import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('create_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('create_rules - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -35,13 +38,15 @@ describe('create_rules', () => { ml = mlServicesMock.createSetupContract(); clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); // no current rules - clients.rulesClient.create.mockResolvedValue(getAlertMock(getQueryRuleParams())); // creation succeeds + clients.rulesClient.create.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); // creation succeeds clients.ruleExecutionLogClient.find.mockResolvedValue(getRuleExecutionStatuses()); // needed to transform: ; context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 1 } }) ); - createRulesRoute(server.router, ml); + createRulesRoute(server.router, ml, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { @@ -57,7 +62,7 @@ describe('create_rules', () => { expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); }); - it('returns 404 if siem client is unavailable', async () => { + test('returns 404 if siem client is unavailable', async () => { const { securitySolution, ...contextWithoutSecuritySolution } = context; // @ts-expect-error const response = await server.inject(getCreateRequest(), contextWithoutSecuritySolution); @@ -65,7 +70,7 @@ describe('create_rules', () => { expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); }); - it('returns 200 if license is not platinum', async () => { + test('returns 200 if license is not platinum', async () => { (context.licensing.license.hasAtLeast as jest.Mock).mockReturnValue(false); const response = await server.inject(getCreateRequest(), context); @@ -74,12 +79,12 @@ describe('create_rules', () => { }); describe('creating an ML Rule', () => { - it('is successful', async () => { + test('is successful', async () => { const response = await server.inject(createMlRuleRequest(), context); expect(response.status).toEqual(200); }); - it('returns a 403 if ML Authz fails', async () => { + test('returns a 403 if ML Authz fails', async () => { (buildMlAuthz as jest.Mock).mockReturnValueOnce({ validateRuleType: jest .fn() @@ -96,21 +101,24 @@ describe('create_rules', () => { }); describe('unhappy paths', () => { - test('it returns a 400 if the index does not exist', async () => { + test('it returns a 400 if the index does not exist when rule registry not enabled', async () => { context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 0 } }) ); const response = await server.inject(getCreateRequest(), context); - expect(response.status).toEqual(400); - expect(response.body).toEqual({ - message: 'To create a rule, the index must exist first. Index undefined does not exist', - status_code: 400, - }); + expect(response.status).toEqual(isRuleRegistryEnabled ? 200 : 400); + + if (!isRuleRegistryEnabled) { + expect(response.body).toEqual({ + message: 'To create a rule, the index must exist first. Index undefined does not exist', + status_code: 400, + }); + } }); test('returns a duplicate error if rule_id already exists', async () => { - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const response = await server.inject(getCreateRequest(), context); expect(response.status).toEqual(409); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts index 333fa9c17a75b..9e03e5f8f2143 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts @@ -6,7 +6,6 @@ */ import { transformError, getIndexExists } from '@kbn/securitysolution-es-utils'; -import { IRuleDataClient } from '../../../../../../rule_registry/server'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; import { DETECTION_ENGINE_RULES_URL, @@ -27,7 +26,7 @@ import { convertCreateAPIToInternalSchema } from '../../schemas/rule_converters' export const createRulesRoute = ( router: SecuritySolutionPluginRouter, ml: SetupPlugins['ml'], - ruleDataClient?: IRuleDataClient | null // TODO: Use this for RAC (otherwise delete it) + isRuleRegistryEnabled: boolean ): void => { router.post( { @@ -57,6 +56,7 @@ export const createRulesRoute = ( if (request.body.rule_id != null) { const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, ruleId: request.body.rule_id, id: undefined, @@ -69,7 +69,11 @@ export const createRulesRoute = ( } } - const internalRule = convertCreateAPIToInternalSchema(request.body, siemClient); + const internalRule = convertCreateAPIToInternalSchema( + request.body, + siemClient, + isRuleRegistryEnabled + ); const mlAuthz = buildMlAuthz({ license: context.licensing.license, @@ -83,7 +87,7 @@ export const createRulesRoute = ( esClient.asCurrentUser, internalRule.params.outputIndex ); - if (!indexExists) { + if (!isRuleRegistryEnabled && !indexExists) { return siemResponse.error({ statusCode: 400, body: `To create a rule, the index must exist first. Index ${internalRule.params.outputIndex} does not exist`, @@ -107,14 +111,18 @@ export const createRulesRoute = ( ruleId: createdRule.id, spaceId: context.securitySolution.getSpaceId(), }); - const [validated, errors] = newTransformValidate(createdRule, ruleStatuses[0]); + const [validated, errors] = newTransformValidate( + createdRule, + ruleStatuses[0], + isRuleRegistryEnabled + ); if (errors != null) { return siemResponse.error({ statusCode: 500, body: errors }); } else { return response.ok({ body: validated ?? {} }); } } catch (err) { - const error = transformError(err); + const error = transformError(err as Error); return siemResponse.error({ body: error.message, statusCode: error.statusCode, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts index 66feb3cae724f..7db5651de2c34 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts @@ -18,7 +18,10 @@ import { import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { deleteRulesBulkRoute } from './delete_rules_bulk_route'; -describe('delete_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('delete_rules - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -26,11 +29,11 @@ describe('delete_rules', () => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // rule exists + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); // rule exists clients.rulesClient.delete.mockResolvedValue({}); // successful deletion clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse()); // rule status request - deleteRulesBulkRoute(server.router); + deleteRulesBulkRoute(server.router, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts index 7a5b7121eb33b..6aecfff1178bc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts @@ -6,6 +6,7 @@ */ import { validate } from '@kbn/securitysolution-io-ts-utils'; + import { queryRuleValidateTypeDependents } from '../../../../../common/detection_engine/schemas/request/query_rules_type_dependents'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; import { @@ -34,7 +35,10 @@ type Handler = RequestHandler< 'delete' | 'post' >; -export const deleteRulesBulkRoute = (router: SecuritySolutionPluginRouter) => { +export const deleteRulesBulkRoute = ( + router: SecuritySolutionPluginRouter, + isRuleRegistryEnabled: boolean +) => { const config: Config = { validate: { body: buildRouteValidation( @@ -71,7 +75,7 @@ export const deleteRulesBulkRoute = (router: SecuritySolutionPluginRouter) => { } try { - const rule = await readRules({ rulesClient, id, ruleId }); + const rule = await readRules({ rulesClient, id, ruleId, isRuleRegistryEnabled }); if (!rule) { return getIdBulkError({ id, ruleId }); } @@ -87,7 +91,12 @@ export const deleteRulesBulkRoute = (router: SecuritySolutionPluginRouter) => { ruleStatuses, id: rule.id, }); - return transformValidateBulkError(idOrRuleIdOrUnknown, rule, ruleStatuses); + return transformValidateBulkError( + idOrRuleIdOrUnknown, + rule, + ruleStatuses, + isRuleRegistryEnabled + ); } catch (err) { return transformBulkError(idOrRuleIdOrUnknown, err); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts index 5102cb32a4572..35b3ef3d9cf85 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts @@ -19,7 +19,10 @@ import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { deleteRulesRoute } from './delete_rules_route'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; -describe('delete_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('delete_rules - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -27,11 +30,11 @@ describe('delete_rules', () => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse()); clients.ruleExecutionLogClient.find.mockResolvedValue(getRuleExecutionStatuses()); - deleteRulesRoute(server.router); + deleteRulesRoute(server.router, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { @@ -42,7 +45,9 @@ describe('delete_rules', () => { }); test('returns 200 when deleting a single rule with a valid actionClient and alertClient by id', async () => { - clients.rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); + clients.rulesClient.get.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); const response = await server.inject(getDeleteRequestById(), context); expect(response.status).toEqual(200); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.ts index 499f5c151c66c..77b8dd6fc5b54 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.ts @@ -6,7 +6,6 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; -import { IRuleDataClient } from '../../../../../../rule_registry/server'; import { queryRuleValidateTypeDependents } from '../../../../../common/detection_engine/schemas/request/query_rules_type_dependents'; import { queryRulesSchema, @@ -23,7 +22,7 @@ import { readRules } from '../../rules/read_rules'; export const deleteRulesRoute = ( router: SecuritySolutionPluginRouter, - ruleDataClient?: IRuleDataClient | null + isRuleRegistryEnabled: boolean ) => { router.delete( { @@ -54,7 +53,7 @@ export const deleteRulesRoute = ( } const ruleStatusClient = context.securitySolution.getExecutionLogClient(); - const rule = await readRules({ rulesClient, id, ruleId }); + const rule = await readRules({ isRuleRegistryEnabled, rulesClient, id, ruleId }); if (!rule) { const error = getIdError({ id, ruleId }); return siemResponse.error({ @@ -74,7 +73,7 @@ export const deleteRulesRoute = ( ruleStatuses, id: rule.id, }); - const transformed = transform(rule, ruleStatuses[0]); + const transformed = transform(rule, ruleStatuses[0], isRuleRegistryEnabled); if (transformed == null) { return siemResponse.error({ statusCode: 500, body: 'failed to transform alert' }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts index 022118859aa0b..e4b99e63cb6c6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts @@ -21,7 +21,11 @@ import { getExportByObjectIds } from '../../rules/get_export_by_object_ids'; import { getExportAll } from '../../rules/get_export_all'; import { buildSiemResponse } from '../utils'; -export const exportRulesRoute = (router: SecuritySolutionPluginRouter, config: ConfigType) => { +export const exportRulesRoute = ( + router: SecuritySolutionPluginRouter, + config: ConfigType, + isRuleRegistryEnabled: boolean +) => { router.post( { path: `${DETECTION_ENGINE_RULES_URL}/_export`, @@ -53,7 +57,10 @@ export const exportRulesRoute = (router: SecuritySolutionPluginRouter, config: C body: `Can't export more than ${exportSizeLimit} rules`, }); } else { - const nonPackagedRulesCount = await getNonPackagedRulesCount({ rulesClient }); + const nonPackagedRulesCount = await getNonPackagedRulesCount({ + isRuleRegistryEnabled, + rulesClient, + }); if (nonPackagedRulesCount > exportSizeLimit) { return siemResponse.error({ statusCode: 400, @@ -64,8 +71,8 @@ export const exportRulesRoute = (router: SecuritySolutionPluginRouter, config: C const exported = request.body?.objects != null - ? await getExportByObjectIds(rulesClient, request.body.objects) - : await getExportAll(rulesClient); + ? await getExportByObjectIds(rulesClient, request.body.objects, isRuleRegistryEnabled) + : await getExportAll(rulesClient, isRuleRegistryEnabled); const responseBody = request.query.exclude_export_details ? exported.rulesNdjson diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts index 301cf8518b838..d15d31dcd63e8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts @@ -17,7 +17,10 @@ import { } from '../__mocks__/request_responses'; import { findRulesRoute } from './find_rules_route'; -describe('find_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('find_rules - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -25,12 +28,14 @@ describe('find_rules', () => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - clients.rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + clients.rulesClient.get.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse()); clients.ruleExecutionLogClient.findBulk.mockResolvedValue(getFindBulkResultStatus()); - findRulesRoute(server.router); + findRulesRoute(server.router, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.ts index ed39d42c38e4a..26e8d1107237b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.ts @@ -6,7 +6,6 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; -import { IRuleDataClient } from '../../../../../../rule_registry/server'; import { findRuleValidateTypeDependents } from '../../../../../common/detection_engine/schemas/request/find_rules_type_dependents'; import { findRulesSchema, @@ -21,7 +20,7 @@ import { transformFindAlerts } from './utils'; export const findRulesRoute = ( router: SecuritySolutionPluginRouter, - ruleDataClient?: IRuleDataClient | null + isRuleRegistryEnabled: boolean ) => { router.get( { @@ -52,6 +51,7 @@ export const findRulesRoute = ( const execLogClient = context.securitySolution.getExecutionLogClient(); const rules = await findRules({ + isRuleRegistryEnabled, rulesClient, perPage: query.per_page, page: query.page, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts index d9b6f4dd0f10c..053e0b7178de5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts @@ -17,7 +17,10 @@ import { RuleStatusResponse } from '../../rules/types'; import { AlertExecutionStatusErrorReasons } from '../../../../../../alerting/common'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; -describe('find_statuses', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('find_statuses - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -25,7 +28,9 @@ describe('find_statuses', () => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); clients.ruleExecutionLogClient.findBulk.mockResolvedValue(getFindBulkResultStatus()); // successful status search - clients.rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); + clients.rulesClient.get.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); findRulesStatusesRoute(server.router); }); @@ -57,7 +62,7 @@ describe('find_statuses', () => { test('returns success if rule status client writes an error status', async () => { // 0. task manager tried to run the rule but couldn't, so the alerting framework // wrote an error to the executionStatus. - const failingExecutionRule = getAlertMock(getQueryRuleParams()); + const failingExecutionRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); failingExecutionRule.executionStatus = { status: 'error', lastExecutionDate: failingExecutionRule.executionStatus.lastExecutionDate, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts index 61c618dc4d5e6..1b171f693d80b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts @@ -51,7 +51,10 @@ jest.mock('../../../timeline/utils/check_timelines_status', () => { }; }); -describe('get_prepackaged_rule_status_route', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('get_prepackaged_rule_status_route - %s', (_, isRuleRegistryEnabled) => { const mockGetCurrentUser = { user: { username: 'mockUser', @@ -63,6 +66,7 @@ describe('get_prepackaged_rule_status_route', () => { let securitySetup: SecurityPluginSetup; beforeEach(() => { + jest.clearAllMocks(); server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); @@ -75,7 +79,18 @@ describe('get_prepackaged_rule_status_route', () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); - getPrepackagedRulesStatusRoute(server.router, createMockConfig(), securitySetup); + (checkTimelinesStatus as jest.Mock).mockResolvedValue({ + timelinesToInstall: [], + timelinesToUpdate: [], + prepackagedTimelines: [], + }); + + getPrepackagedRulesStatusRoute( + server.router, + createMockConfig(), + securitySetup, + isRuleRegistryEnabled + ); }); describe('status codes with actionClient and alertClient', () => { @@ -123,7 +138,7 @@ describe('get_prepackaged_rule_status_route', () => { }); test('1 rule installed, 1 custom rules, 0 rules not installed, and 1 rule to not updated', async () => { - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const request = getPrepackagedRulesStatusRequest(); const response = await server.inject(request, context); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts index 38c315462bf55..9a06928eee233 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.ts @@ -32,7 +32,8 @@ import { export const getPrepackagedRulesStatusRoute = ( router: SecuritySolutionPluginRouter, config: ConfigType, - security: SetupPlugins['security'] + security: SetupPlugins['security'], + isRuleRegistryEnabled: boolean ) => { router.get( { @@ -59,6 +60,7 @@ export const getPrepackagedRulesStatusRoute = ( config.prebuiltRulesFromSavedObjects ); const customRules = await findRules({ + isRuleRegistryEnabled, rulesClient, perPage: 1, page: 1, @@ -68,7 +70,10 @@ export const getPrepackagedRulesStatusRoute = ( fields: undefined, }); const frameworkRequest = await buildFrameworkRequest(context, security, request); - const prepackagedRules = await getExistingPrepackagedRules({ rulesClient }); + const prepackagedRules = await getExistingPrepackagedRules({ + rulesClient, + isRuleRegistryEnabled, + }); const rulesToInstall = getRulesToInstall(latestPrepackagedRules, prepackagedRules); const rulesToUpdate = getRulesToUpdate(latestPrepackagedRules, prepackagedRules); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts index cd572894f551e..bf29dbe870153 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts @@ -29,7 +29,10 @@ import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('import_rules_route', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('import_rules_route - %s', (_, isRuleRegistryEnabled) => { let config: ReturnType; let server: ReturnType; let request: ReturnType; @@ -45,11 +48,13 @@ describe('import_rules_route', () => { ml = mlServicesMock.createSetupContract(); clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); // no extant rules - clients.rulesClient.update.mockResolvedValue(getAlertMock(getQueryRuleParams())); + clients.rulesClient.update.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 1 } }) ); - importRulesRoute(server.router, config, ml); + importRulesRoute(server.router, config, ml, isRuleRegistryEnabled); }); describe('status codes', () => { @@ -60,7 +65,7 @@ describe('import_rules_route', () => { }); test('returns 500 if more than 10,000 rules are imported', async () => { - const ruleIds = new Array(10001).fill(undefined).map((_, index) => `rule-${index}`); + const ruleIds = new Array(10001).fill(undefined).map((__, index) => `rule-${index}`); const multiRequest = getImportRulesRequest(buildHapiStream(ruleIdsToNdJsonString(ruleIds))); const response = await server.inject(multiRequest, context); @@ -125,18 +130,20 @@ describe('import_rules_route', () => { transformMock.mockRestore(); }); - test('returns an error if the index does not exist', async () => { + test('returns an error if the index does not exist when rule registry not enabled', async () => { clients.appClient.getSignalsIndex.mockReturnValue('mockSignalsIndex'); context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise({ _shards: { total: 0 } }) ); const response = await server.inject(request, context); - expect(response.status).toEqual(400); - expect(response.body).toEqual({ - message: - 'To create a rule, the index must exist first. Index mockSignalsIndex does not exist', - status_code: 400, - }); + expect(response.status).toEqual(isRuleRegistryEnabled ? 200 : 400); + if (!isRuleRegistryEnabled) { + expect(response.body).toEqual({ + message: + 'To create a rule, the index must exist first. Index mockSignalsIndex does not exist', + status_code: 400, + }); + } }); test('returns an error when cluster throws error', async () => { @@ -166,7 +173,9 @@ describe('import_rules_route', () => { describe('single rule import', () => { test('returns 200 if rule imported successfully', async () => { - clients.rulesClient.create.mockResolvedValue(getAlertMock(getQueryRuleParams())); + clients.rulesClient.create.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); const response = await server.inject(request, context); expect(response.status).toEqual(200); expect(response.body).toEqual({ @@ -199,7 +208,9 @@ describe('import_rules_route', () => { describe('rule with existing rule_id', () => { test('returns with reported conflict if `overwrite` is set to `false`', async () => { - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // extant rule + clients.rulesClient.find.mockResolvedValue( + getFindResultWithSingleHit(isRuleRegistryEnabled) + ); // extant rule const response = await server.inject(request, context); expect(response.status).toEqual(200); @@ -219,7 +230,9 @@ describe('import_rules_route', () => { }); test('returns with NO reported conflict if `overwrite` is set to `true`', async () => { - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // extant rule + clients.rulesClient.find.mockResolvedValue( + getFindResultWithSingleHit(isRuleRegistryEnabled) + ); // extant rule const overwriteRequest = getImportRulesRequestOverwriteTrue( buildHapiStream(ruleIdsToNdJsonString(['rule-1'])) ); @@ -251,7 +264,7 @@ describe('import_rules_route', () => { }); test('returns 200 if many rules are imported successfully', async () => { - const ruleIds = new Array(9999).fill(undefined).map((_, index) => `rule-${index}`); + const ruleIds = new Array(9999).fill(undefined).map((__, index) => `rule-${index}`); const multiRequest = getImportRulesRequest(buildHapiStream(ruleIdsToNdJsonString(ruleIds))); const response = await server.inject(multiRequest, context); @@ -339,7 +352,9 @@ describe('import_rules_route', () => { describe('rules with existing rule_id', () => { beforeEach(() => { - clients.rulesClient.find.mockResolvedValueOnce(getFindResultWithSingleHit()); // extant rule + clients.rulesClient.find.mockResolvedValueOnce( + getFindResultWithSingleHit(isRuleRegistryEnabled) + ); // extant rule }); test('returns with reported conflict if `overwrite` is set to `false`', async () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts index d3193900859fa..8269fe8b36132 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts @@ -53,7 +53,8 @@ const CHUNK_PARSED_OBJECT_SIZE = 50; export const importRulesRoute = ( router: SecuritySolutionPluginRouter, config: ConfigType, - ml: SetupPlugins['ml'] + ml: SetupPlugins['ml'], + isRuleRegistryEnabled: boolean ) => { router.post( { @@ -103,7 +104,7 @@ export const importRulesRoute = ( } const signalsIndex = siemClient.getSignalsIndex(); const indexExists = await getIndexExists(esClient.asCurrentUser, signalsIndex); - if (!indexExists) { + if (!isRuleRegistryEnabled && !indexExists) { return siemResponse.error({ statusCode: 400, body: `To create a rule, the index must exist first. Index ${signalsIndex} does not exist`, @@ -205,6 +206,7 @@ export const importRulesRoute = ( const filters: PartialFilter[] | undefined = filtersRest as PartialFilter[]; throwHttpError(await mlAuthz.validateRuleType(type)); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, ruleId, id: undefined, @@ -212,6 +214,7 @@ export const importRulesRoute = ( if (rule == null) { await createRules({ + isRuleRegistryEnabled, rulesClient, anomalyThreshold, author, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts index 31f805c563f76..2c3db023dccc4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts @@ -22,7 +22,10 @@ import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('patch_rules_bulk', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('patch_rules_bulk - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -32,10 +35,12 @@ describe('patch_rules_bulk', () => { ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // rule exists - clients.rulesClient.update.mockResolvedValue(getAlertMock(getQueryRuleParams())); // update succeeds + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); // rule exists + clients.rulesClient.update.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); // update succeeds - patchRulesBulkRoute(server.router, ml); + patchRulesBulkRoute(server.router, ml, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts index 3aaa82ea56f3f..67d68221d846f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.ts @@ -27,7 +27,8 @@ import { PartialFilter } from '../../types'; export const patchRulesBulkRoute = ( router: SecuritySolutionPluginRouter, - ml: SetupPlugins['ml'] + ml: SetupPlugins['ml'], + isRuleRegistryEnabled: boolean ) => { router.patch( { @@ -121,7 +122,12 @@ export const patchRulesBulkRoute = ( throwHttpError(await mlAuthz.validateRuleType(type)); } - const existingRule = await readRules({ rulesClient, ruleId, id }); + const existingRule = await readRules({ + isRuleRegistryEnabled, + rulesClient, + ruleId, + id, + }); if (existingRule?.params.type) { // reject an unauthorized modification of an ML rule throwHttpError(await mlAuthz.validateRuleType(existingRule?.params.type)); @@ -185,7 +191,7 @@ export const patchRulesBulkRoute = ( ruleId: rule.id, spaceId: context.securitySolution.getSpaceId(), }); - return transformValidateBulkError(rule.id, rule, ruleStatuses); + return transformValidateBulkError(rule.id, rule, ruleStatuses, isRuleRegistryEnabled); } else { return getIdBulkError({ id, ruleId }); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts index 16d65d6482d21..97773c45ce0d9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts @@ -25,7 +25,10 @@ import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('patch_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('patch_rules - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -35,14 +38,18 @@ describe('patch_rules', () => { ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); - clients.rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); // existing rule - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // existing rule - clients.rulesClient.update.mockResolvedValue(getAlertMock(getQueryRuleParams())); // successful update + clients.rulesClient.get.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); // existing rule + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); // existing rule + clients.rulesClient.update.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); // successful update clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse()); // successful transform clients.savedObjectsClient.create.mockResolvedValue(getRuleExecutionStatuses()[0]); // successful transform clients.ruleExecutionLogClient.find.mockResolvedValue(getRuleExecutionStatuses()); - patchRulesRoute(server.router, ml); + patchRulesRoute(server.router, ml, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { @@ -69,7 +76,7 @@ describe('patch_rules', () => { }); test('returns error if requesting a non-rule', async () => { - clients.rulesClient.find.mockResolvedValue(nonRuleFindResult()); + clients.rulesClient.find.mockResolvedValue(nonRuleFindResult(isRuleRegistryEnabled)); const response = await server.inject(getPatchRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts index b564262b4a5c7..cf140f22289de 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.ts @@ -6,7 +6,6 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; -import { IRuleDataClient } from '../../../../../../rule_registry/server'; import { RuleAlertAction } from '../../../../../common/detection_engine/types'; import { patchRuleValidateTypeDependents } from '../../../../../common/detection_engine/schemas/request/patch_rules_type_dependents'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; @@ -30,7 +29,7 @@ import { PartialFilter } from '../../types'; export const patchRulesRoute = ( router: SecuritySolutionPluginRouter, ml: SetupPlugins['ml'], - ruleDataClient?: IRuleDataClient | null + isRuleRegistryEnabled: boolean ) => { router.patch( { @@ -124,7 +123,12 @@ export const patchRulesRoute = ( throwHttpError(await mlAuthz.validateRuleType(type)); } - const existingRule = await readRules({ rulesClient, ruleId, id }); + const existingRule = await readRules({ + isRuleRegistryEnabled, + rulesClient, + ruleId, + id, + }); if (existingRule?.params.type) { // reject an unauthorized modification of an ML rule throwHttpError(await mlAuthz.validateRuleType(existingRule?.params.type)); @@ -189,7 +193,11 @@ export const patchRulesRoute = ( spaceId: context.securitySolution.getSpaceId(), }); - const [validated, errors] = transformValidate(rule, ruleStatuses[0]); + const [validated, errors] = transformValidate( + rule, + ruleStatuses[0], + isRuleRegistryEnabled + ); if (errors != null) { return siemResponse.error({ statusCode: 500, body: errors }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts index f8b3b834af857..ebc86acc964e6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts @@ -20,7 +20,10 @@ import { getPerformBulkActionSchemaMock } from '../../../../../common/detection_ jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('perform_bulk_action', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('perform_bulk_action - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -30,9 +33,9 @@ describe('perform_bulk_action', () => { ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); - performBulkActionRoute(server.router, ml); + performBulkActionRoute(server.router, ml, isRuleRegistryEnabled); }); describe('status codes', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts index 70198d081ebfa..0eba5af4e063a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts @@ -25,7 +25,8 @@ const BULK_ACTION_RULES_LIMIT = 10000; export const performBulkActionRoute = ( router: SecuritySolutionPluginRouter, - ml: SetupPlugins['ml'] + ml: SetupPlugins['ml'], + isRuleRegistryEnabled: boolean ) => { router.post( { @@ -58,6 +59,7 @@ export const performBulkActionRoute = ( } const rules = await findRules({ + isRuleRegistryEnabled, rulesClient, perPage: BULK_ACTION_RULES_LIMIT, filter: body.query !== '' ? body.query : undefined, @@ -131,7 +133,8 @@ export const performBulkActionRoute = ( case BulkAction.export: const exported = await getExportByObjectIds( rulesClient, - rules.data.map(({ params }) => ({ rule_id: params.ruleId })) + rules.data.map(({ params }) => ({ rule_id: params.ruleId })), + isRuleRegistryEnabled ); const responseBody = `${exported.rulesNdjson}${exported.exportDetails}`; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts index 586ff027425f8..057cbf4c12966 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts @@ -16,7 +16,10 @@ import { } from '../__mocks__/request_responses'; import { requestMock, requestContextMock, serverMock } from '../__mocks__'; -describe('read_signals', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('read_rules - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -24,11 +27,11 @@ describe('read_signals', () => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // rule exists + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); // rule exists clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse()); // successful transform clients.ruleExecutionLogClient.find.mockResolvedValue([]); - readRulesRoute(server.router); + readRulesRoute(server.router, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { @@ -45,7 +48,7 @@ describe('read_signals', () => { }); test('returns error if requesting a non-rule', async () => { - clients.rulesClient.find.mockResolvedValue(nonRuleFindResult()); + clients.rulesClient.find.mockResolvedValue(nonRuleFindResult(isRuleRegistryEnabled)); const response = await server.inject(getReadRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.ts index 7aef65e7918b2..5672648190653 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.ts @@ -6,7 +6,6 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; -import { IRuleDataClient } from '../../../../../../rule_registry/server'; import { queryRuleValidateTypeDependents } from '../../../../../common/detection_engine/schemas/request/query_rules_type_dependents'; import { queryRulesSchema, @@ -23,7 +22,7 @@ import { RuleExecutionStatus } from '../../../../../common/detection_engine/sche export const readRulesRoute = ( router: SecuritySolutionPluginRouter, - ruleDataClient?: IRuleDataClient | null + isRuleRegistryEnabled: boolean ) => { router.get( { @@ -55,8 +54,9 @@ export const readRulesRoute = ( const ruleStatusClient = context.securitySolution.getExecutionLogClient(); const rule = await readRules({ - rulesClient, id, + isRuleRegistryEnabled, + rulesClient, ruleId, }); if (rule != null) { @@ -72,7 +72,7 @@ export const readRulesRoute = ( currentStatus.attributes.statusDate = rule.executionStatus.lastExecutionDate.toISOString(); currentStatus.attributes.status = RuleExecutionStatus.failed; } - const transformed = transform(rule, currentStatus); + const transformed = transform(rule, currentStatus, isRuleRegistryEnabled); if (transformed == null) { return siemResponse.error({ statusCode: 500, body: 'Internal error transforming' }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts index eeb8b3caf6df5..746a40dfa8dc2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts @@ -23,7 +23,10 @@ import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('update_rules_bulk', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('update_rules_bulk - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -33,10 +36,12 @@ describe('update_rules_bulk', () => { ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - clients.rulesClient.update.mockResolvedValue(getAlertMock(getQueryRuleParams())); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + clients.rulesClient.update.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); - updateRulesBulkRoute(server.router, ml); + updateRulesBulkRoute(server.router, ml, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts index 389c49d3cff4e..6138690070b62 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts @@ -22,7 +22,8 @@ import { updateRules } from '../../rules/update_rules'; export const updateRulesBulkRoute = ( router: SecuritySolutionPluginRouter, - ml: SetupPlugins['ml'] + ml: SetupPlugins['ml'], + isRuleRegistryEnabled: boolean ) => { router.put( { @@ -74,6 +75,7 @@ export const updateRulesBulkRoute = ( ruleStatusClient, defaultOutputIndex: siemClient.getSignalsIndex(), ruleUpdate: payloadRule, + isRuleRegistryEnabled, }); if (rule != null) { const ruleStatuses = await ruleStatusClient.find({ @@ -81,7 +83,7 @@ export const updateRulesBulkRoute = ( ruleId: rule.id, spaceId: context.securitySolution.getSpaceId(), }); - return transformValidateBulkError(rule.id, rule, ruleStatuses); + return transformValidateBulkError(rule.id, rule, ruleStatuses, isRuleRegistryEnabled); } else { return getIdBulkError({ id: payloadRule.id, ruleId: payloadRule.rule_id }); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index db0054088137c..5b3e2737418c2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -23,7 +23,10 @@ import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); -describe('update_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('update_rules - %s', (_, isRuleRegistryEnabled) => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); let ml: ReturnType; @@ -33,12 +36,16 @@ describe('update_rules', () => { ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); - clients.rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); // existing rule - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // rule exists - clients.rulesClient.update.mockResolvedValue(getAlertMock(getQueryRuleParams())); // successful update + clients.rulesClient.get.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); // existing rule + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); // rule exists + clients.rulesClient.update.mockResolvedValue( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); // successful update clients.ruleExecutionLogClient.find.mockResolvedValue([]); // successful transform: ; - updateRulesRoute(server.router, ml); + updateRulesRoute(server.router, ml, isRuleRegistryEnabled); }); describe('status codes with actionClient and alertClient', () => { @@ -75,7 +82,7 @@ describe('update_rules', () => { }); test('returns error when updating non-rule', async () => { - clients.rulesClient.find.mockResolvedValue(nonRuleFindResult()); + clients.rulesClient.find.mockResolvedValue(nonRuleFindResult(isRuleRegistryEnabled)); const response = await server.inject(getUpdateRequest(), context); expect(response.status).toEqual(404); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts index ecf61bec2b20a..7cfe83093a549 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.ts @@ -6,7 +6,6 @@ */ import { transformError } from '@kbn/securitysolution-es-utils'; -import { IRuleDataClient } from '../../../../../../rule_registry/server'; import { updateRulesSchema } from '../../../../../common/detection_engine/schemas/request'; import { updateRuleValidateTypeDependents } from '../../../../../common/detection_engine/schemas/request/update_rules_type_dependents'; import type { SecuritySolutionPluginRouter } from '../../../../types'; @@ -24,7 +23,7 @@ import { buildRouteValidation } from '../../../../utils/build_validation/route_v export const updateRulesRoute = ( router: SecuritySolutionPluginRouter, ml: SetupPlugins['ml'], - ruleDataClient?: IRuleDataClient | null + isRuleRegistryEnabled: boolean ) => { router.put( { @@ -61,11 +60,12 @@ export const updateRulesRoute = ( const ruleStatusClient = context.securitySolution.getExecutionLogClient(); const rule = await updateRules({ - spaceId: context.securitySolution.getSpaceId(), + defaultOutputIndex: siemClient.getSignalsIndex(), + isRuleRegistryEnabled, rulesClient, ruleStatusClient, - defaultOutputIndex: siemClient.getSignalsIndex(), ruleUpdate: request.body, + spaceId: context.securitySolution.getSpaceId(), }); if (rule != null) { @@ -74,7 +74,11 @@ export const updateRulesRoute = ( ruleId: rule.id, spaceId: context.securitySolution.getSpaceId(), }); - const [validated, errors] = transformValidate(rule, ruleStatuses[0]); + const [validated, errors] = transformValidate( + rule, + ruleStatuses[0], + isRuleRegistryEnabled + ); if (errors != null) { return siemResponse.error({ statusCode: 500, body: errors }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts index 0018a37016980..f07a63b690a2d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts @@ -41,16 +41,19 @@ import { type PromiseFromStreams = ImportRulesSchemaDecoded | Error; -describe('utils', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('utils - %s', (_, isRuleRegistryEnabled) => { describe('transformAlertToRule', () => { test('should work with a full data set', () => { - const fullRule = getAlertMock(getQueryRuleParams()); + const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); const rule = transformAlertToRule(fullRule); expect(rule).toEqual(getOutputRuleAlertForRest()); }); test('should omit note if note is undefined', () => { - const fullRule = getAlertMock(getQueryRuleParams()); + const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.params.note = undefined; const rule = transformAlertToRule(fullRule); const { note, ...expectedWithoutNote } = getOutputRuleAlertForRest(); @@ -58,7 +61,7 @@ describe('utils', () => { }); test('should return enabled is equal to false', () => { - const fullRule = getAlertMock(getQueryRuleParams()); + const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.enabled = false; const ruleWithEnabledFalse = transformAlertToRule(fullRule); const expected = getOutputRuleAlertForRest(); @@ -67,7 +70,7 @@ describe('utils', () => { }); test('should return immutable is equal to false', () => { - const fullRule = getAlertMock(getQueryRuleParams()); + const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.params.immutable = false; const ruleWithEnabledFalse = transformAlertToRule(fullRule); const expected = getOutputRuleAlertForRest(); @@ -75,7 +78,7 @@ describe('utils', () => { }); test('should work with tags but filter out any internal tags', () => { - const fullRule = getAlertMock(getQueryRuleParams()); + const fullRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); fullRule.tags = ['tag 1', 'tag 2', `${INTERNAL_IDENTIFIER}_some_other_value`]; const rule = transformAlertToRule(fullRule); const expected = getOutputRuleAlertForRest(); @@ -84,7 +87,7 @@ describe('utils', () => { }); test('transforms ML Rule fields', () => { - const mlRule = getAlertMock(getMlRuleParams()); + const mlRule = getAlertMock(isRuleRegistryEnabled, getMlRuleParams()); mlRule.params.anomalyThreshold = 55; mlRule.params.machineLearningJobId = ['some_job_id']; mlRule.params.type = 'machine_learning'; @@ -100,7 +103,7 @@ describe('utils', () => { }); test('transforms threat_matching fields', () => { - const threatRule = getAlertMock(getThreatRuleParams()); + const threatRule = getAlertMock(isRuleRegistryEnabled, getThreatRuleParams()); const threatFilters: PartialFilter[] = [ { query: { @@ -153,7 +156,7 @@ describe('utils', () => { test('does not leak a lists structure in the transform which would cause validation issues', () => { const result: RuleAlertType & { lists: [] } = { lists: [], - ...getAlertMock(getQueryRuleParams()), + ...getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), }; const rule = transformAlertToRule(result); expect(rule).toEqual( @@ -168,7 +171,7 @@ describe('utils', () => { test('does not leak an exceptions_list structure in the transform which would cause validation issues', () => { const result: RuleAlertType & { exceptions_list: [] } = { exceptions_list: [], - ...getAlertMock(getQueryRuleParams()), + ...getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), }; const rule = transformAlertToRule(result); expect(rule).toEqual( @@ -265,7 +268,7 @@ describe('utils', () => { page: 1, perPage: 0, total: 0, - data: [getAlertMock(getQueryRuleParams())], + data: [getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())], }, {} ); @@ -281,14 +284,18 @@ describe('utils', () => { describe('transform', () => { test('outputs 200 if the data is of type siem alert', () => { - const output = transform(getAlertMock(getQueryRuleParams())); + const output = transform( + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), + undefined, + isRuleRegistryEnabled + ); const expected = getOutputRuleAlertForRest(); expect(output).toEqual(expected); }); test('returns 500 if the data is not of type siem alert', () => { const unsafeCast = ({ data: [{ random: 1 }] } as unknown) as PartialAlert; - const output = transform(unsafeCast); + const output = transform(unsafeCast, undefined, isRuleRegistryEnabled); expect(output).toBeNull(); }); }); @@ -396,24 +403,34 @@ describe('utils', () => { describe('transformOrBulkError', () => { test('outputs 200 if the data is of type siem alert', () => { - const output = transformOrBulkError('rule-1', getAlertMock(getQueryRuleParams()), { - id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', - actions: [], - ruleThrottle: 'no_actions', - alertThrottle: null, - }); + const output = transformOrBulkError( + 'rule-1', + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), + { + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + actions: [], + ruleThrottle: 'no_actions', + alertThrottle: null, + }, + isRuleRegistryEnabled + ); const expected = getOutputRuleAlertForRest(); expect(output).toEqual(expected); }); test('returns 500 if the data is not of type siem alert', () => { const unsafeCast = ({ name: 'something else' } as unknown) as PartialAlert; - const output = transformOrBulkError('rule-1', unsafeCast, { - id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', - actions: [], - ruleThrottle: 'no_actions', - alertThrottle: null, - }); + const output = transformOrBulkError( + 'rule-1', + unsafeCast, + { + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + actions: [], + ruleThrottle: 'no_actions', + alertThrottle: null, + }, + isRuleRegistryEnabled + ); const expected: BulkError = { rule_id: 'rule-1', error: { message: 'Internal error transforming', status_code: 500 }, @@ -428,15 +445,15 @@ describe('utils', () => { }); test('given single alert will return the alert transformed', () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); const transformed = transformAlertsToRules([result1]); const expected = getOutputRuleAlertForRest(); expect(transformed).toEqual([expected]); }); test('given two alerts will return the two alerts transformed', () => { - const result1 = getAlertMock(getQueryRuleParams()); - const result2 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = 'some other id'; result2.params.ruleId = 'some other id'; @@ -451,11 +468,16 @@ describe('utils', () => { describe('transformOrImportError', () => { test('returns 1 given success if the alert is an alert type and the existing success count is 0', () => { - const output = transformOrImportError('rule-1', getAlertMock(getQueryRuleParams()), { - success: true, - success_count: 0, - errors: [], - }); + const output = transformOrImportError( + 'rule-1', + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), + { + success: true, + success_count: 0, + errors: [], + }, + isRuleRegistryEnabled + ); const expected: ImportSuccessError = { success: true, errors: [], @@ -465,11 +487,16 @@ describe('utils', () => { }); test('returns 2 given successes if the alert is an alert type and the existing success count is 1', () => { - const output = transformOrImportError('rule-1', getAlertMock(getQueryRuleParams()), { - success: true, - success_count: 1, - errors: [], - }); + const output = transformOrImportError( + 'rule-1', + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), + { + success: true, + success_count: 1, + errors: [], + }, + isRuleRegistryEnabled + ); const expected: ImportSuccessError = { success: true, errors: [], @@ -480,11 +507,16 @@ describe('utils', () => { test('returns 1 error and success of false if the data is not of type siem alert', () => { const unsafeCast = ({ name: 'something else' } as unknown) as PartialAlert; - const output = transformOrImportError('rule-1', unsafeCast, { - success: true, - success_count: 1, - errors: [], - }); + const output = transformOrImportError( + 'rule-1', + unsafeCast, + { + success: true, + success_count: 1, + errors: [], + }, + isRuleRegistryEnabled + ); const expected: ImportSuccessError = { success: false, errors: [ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts index 6e1faf819c3d5..4f023156fba06 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts @@ -135,9 +135,10 @@ export const transformFindAlerts = ( export const transform = ( alert: PartialAlert, - ruleStatus?: SavedObject + ruleStatus?: SavedObject, + isRuleRegistryEnabled?: boolean ): Partial | null => { - if (isAlertType(alert)) { + if (isAlertType(isRuleRegistryEnabled ?? false, alert)) { return transformAlertToRule( alert, isRuleStatusSavedObjectType(ruleStatus) ? ruleStatus : undefined @@ -150,9 +151,10 @@ export const transform = ( export const transformOrBulkError = ( ruleId: string, alert: PartialAlert, - ruleStatus?: unknown + ruleStatus?: unknown, + isRuleRegistryEnabled?: boolean ): Partial | BulkError => { - if (isAlertType(alert)) { + if (isAlertType(isRuleRegistryEnabled ?? false, alert)) { if (isRuleStatusFindType(ruleStatus) && ruleStatus?.saved_objects.length > 0) { return transformAlertToRule(alert, ruleStatus?.saved_objects[0] ?? ruleStatus); } else { @@ -170,9 +172,10 @@ export const transformOrBulkError = ( export const transformOrImportError = ( ruleId: string, alert: PartialAlert, - existingImportSuccessError: ImportSuccessError + existingImportSuccessError: ImportSuccessError, + isRuleRegistryEnabled: boolean ): ImportSuccessError => { - if (isAlertType(alert)) { + if (isAlertType(isRuleRegistryEnabled, alert)) { return createSuccessObject(existingImportSuccessError); } else { return createImportErrorObject({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts index 9cbd4de71613a..a7ba1ac77b7bf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts @@ -66,20 +66,23 @@ export const ruleOutput = (): RulesSchema => ({ timeline_id: 'some-timeline-id', }); -describe('validate', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('validate - %s', (_, isRuleRegistryEnabled) => { describe('transformValidate', () => { test('it should do a validation correctly of a partial alert', () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); - const [validated, errors] = transformValidate(ruleAlert); + const ruleAlert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); + const [validated, errors] = transformValidate(ruleAlert, undefined, isRuleRegistryEnabled); expect(validated).toEqual(ruleOutput()); expect(errors).toEqual(null); }); test('it should do an in-validation correctly of a partial alert', () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); // @ts-expect-error delete ruleAlert.name; - const [validated, errors] = transformValidate(ruleAlert); + const [validated, errors] = transformValidate(ruleAlert, undefined, isRuleRegistryEnabled); expect(validated).toEqual(null); expect(errors).toEqual('Invalid value "undefined" supplied to "name"'); }); @@ -87,16 +90,26 @@ describe('validate', () => { describe('transformValidateBulkError', () => { test('it should do a validation correctly of a rule id', () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); - const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); + const ruleAlert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); + const validatedOrError = transformValidateBulkError( + 'rule-1', + ruleAlert, + undefined, + isRuleRegistryEnabled + ); expect(validatedOrError).toEqual(ruleOutput()); }); test('it should do an in-validation correctly of a rule id', () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); // @ts-expect-error delete ruleAlert.name; - const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); + const validatedOrError = transformValidateBulkError( + 'rule-1', + ruleAlert, + undefined, + isRuleRegistryEnabled + ); const expected: BulkError = { error: { message: 'Invalid value "undefined" supplied to "name"', @@ -109,8 +122,13 @@ describe('validate', () => { test('it should do a validation correctly of a rule id with ruleStatus passed in', () => { const ruleStatuses = getRuleExecutionStatuses(); - const ruleAlert = getAlertMock(getQueryRuleParams()); - const validatedOrError = transformValidateBulkError('rule-1', ruleAlert, ruleStatuses); + const ruleAlert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); + const validatedOrError = transformValidateBulkError( + 'rule-1', + ruleAlert, + ruleStatuses, + isRuleRegistryEnabled + ); const expected: RulesSchema = { ...ruleOutput(), status: RuleExecutionStatus.succeeded, @@ -122,10 +140,15 @@ describe('validate', () => { }); test('it should return error object if "alert" is not expected alert type', () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); // @ts-expect-error delete ruleAlert.alertTypeId; - const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); + const validatedOrError = transformValidateBulkError( + 'rule-1', + ruleAlert, + undefined, + isRuleRegistryEnabled + ); const expected: BulkError = { error: { message: 'Internal error transforming', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts index ccb3201848e3c..c1969c5088bc0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts @@ -29,9 +29,10 @@ import { RuleParams } from '../../schemas/rule_schemas'; export const transformValidate = ( alert: PartialAlert, - ruleStatus?: SavedObject + ruleStatus?: SavedObject, + isRuleRegistryEnabled?: boolean ): [RulesSchema | null, string | null] => { - const transformed = transform(alert, ruleStatus); + const transformed = transform(alert, ruleStatus, isRuleRegistryEnabled); if (transformed == null) { return [null, 'Internal error transforming']; } else { @@ -41,9 +42,10 @@ export const transformValidate = ( export const newTransformValidate = ( alert: PartialAlert, - ruleStatus?: SavedObject + ruleStatus?: SavedObject, + isRuleRegistryEnabled?: boolean ): [FullResponseSchema | null, string | null] => { - const transformed = transform(alert, ruleStatus); + const transformed = transform(alert, ruleStatus, isRuleRegistryEnabled); if (transformed == null) { return [null, 'Internal error transforming']; } else { @@ -54,9 +56,10 @@ export const newTransformValidate = ( export const transformValidateBulkError = ( ruleId: string, alert: PartialAlert, - ruleStatus?: Array> + ruleStatus?: Array>, + isRuleRegistryEnabled?: boolean ): RulesSchema | BulkError => { - if (isAlertType(alert)) { + if (isAlertType(isRuleRegistryEnabled ?? false, alert)) { if (ruleStatus && ruleStatus?.length > 0 && isRuleStatusSavedObjectType(ruleStatus[0])) { const transformed = transformAlertToRule(alert, ruleStatus[0]); const [validated, errors] = validateNonExact(transformed, rulesSchema); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/tags/read_tags_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/tags/read_tags_route.ts index e22497071b2b7..04464e5d6f5a7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/tags/read_tags_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/tags/read_tags_route.ts @@ -12,7 +12,10 @@ import { buildSiemResponse } from '../utils'; import { readTags } from '../../tags/read_tags'; -export const readTagsRoute = (router: SecuritySolutionPluginRouter) => { +export const readTagsRoute = ( + router: SecuritySolutionPluginRouter, + isRuleRegistryEnabled: boolean +) => { router.get( { path: DETECTION_ENGINE_TAGS_URL, @@ -31,6 +34,7 @@ export const readTagsRoute = (router: SecuritySolutionPluginRouter) => { try { const tags = await readTags({ + isRuleRegistryEnabled, rulesClient, }); return response.ok({ body: tags }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts index c7e1f9f2e6bd7..23a65b456e6bc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts @@ -33,7 +33,10 @@ import { RuleExecutionStatus } from '../../../../common/detection_engine/schemas let rulesClient: ReturnType; -describe('utils', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('utils - %s', (_, isRuleRegistryEnabled) => { describe('transformBulkError', () => { test('returns transformed object if it is a boom object', () => { const boom = new Boom.Boom('some boom message', { statusCode: 400 }); @@ -390,12 +393,12 @@ describe('utils', () => { rulesClient = rulesClientMock.create(); }); it('getFailingRules finds no failing rules', async () => { - rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); + rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); const res = await getFailingRules(['my-fake-id'], rulesClient); expect(res).toEqual({}); }); it('getFailingRules finds a failing rule', async () => { - const foundRule = getAlertMock(getQueryRuleParams()); + const foundRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); foundRule.executionStatus = { status: 'error', lastExecutionDate: foundRule.executionStatus.lastExecutionDate, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts index 8f078b01daf73..775115ded7c4f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts @@ -328,6 +328,6 @@ export const getFailingRules = async ( if (Boom.isBoom(exc)) { throw exc; } - throw new Error(`Failed to get executionStatus with RulesClient: ${exc.message}`); + throw new Error(`Failed to get executionStatus with RulesClient: ${(exc as Error).message}`); } }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts index f2dfe69debed0..e2d5da1def707 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.ts @@ -7,7 +7,7 @@ import { validateNonExact } from '@kbn/securitysolution-io-ts-utils'; import { PersistenceServices } from '../../../../../../rule_registry/server'; -import { INDICATOR_ALERT_TYPE_ID } from '../../../../../common/constants'; +import { INDICATOR_RULE_TYPE_ID } from '../../../../../common/constants'; import { threatRuleParams, ThreatRuleParams } from '../../schemas/rule_schemas'; import { threatMatchExecutor } from '../../signals/executors/threat_match'; import { createSecurityRuleTypeFactory } from '../create_security_rule_type_factory'; @@ -33,7 +33,7 @@ export const createIndicatorMatchAlertType = (createOptions: CreateRuleOptions) ruleDataService, }); return createSecurityRuleType({ - id: INDICATOR_ALERT_TYPE_ID, + id: INDICATOR_RULE_TYPE_ID, name: 'Indicator Match Rule', validate: { params: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml.ts index 14252bf62ef83..e0ad333b76a24 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml.ts @@ -14,7 +14,7 @@ import { SavedObject } from 'src/core/types'; import { buildEsQuery, IIndexPattern } from '../../../../../../../src/plugins/data/common'; import { createPersistenceRuleTypeFactory } from '../../../../../rule_registry/server'; -import { ML_ALERT_TYPE_ID } from '../../../../common/constants'; +import { ML_RULE_TYPE_ID } from '../../../../common/constants'; import { SecurityRuleRegistry } from '../../../plugin'; const createSecurityMlRuleType = createPersistenceRuleTypeFactory(); @@ -38,7 +38,7 @@ import { MachineLearningRuleAttributes } from '../signals/types'; import { createErrorsFromShard, createSearchAfterReturnType, mergeReturns } from '../signals/utils'; export const mlAlertType = createSecurityMlRuleType({ - id: ML_ALERT_TYPE_ID, + id: ML_RULE_TYPE_ID, name: 'Machine Learning Rule', validate: { params: schema.object({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts index cdaeb4be76d02..7d891d430c63c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/ml/create_ml_alert_type.ts @@ -7,7 +7,7 @@ import { validateNonExact } from '@kbn/securitysolution-io-ts-utils'; import { PersistenceServices } from '../../../../../../rule_registry/server'; -import { ML_ALERT_TYPE_ID } from '../../../../../common/constants'; +import { ML_RULE_TYPE_ID } from '../../../../../common/constants'; import { machineLearningRuleParams, MachineLearningRuleParams } from '../../schemas/rule_schemas'; import { mlExecutor } from '../../signals/executors/ml'; import { createSecurityRuleTypeFactory } from '../create_security_rule_type_factory'; @@ -32,7 +32,7 @@ export const createMlAlertType = (createOptions: CreateRuleOptions) => { ruleDataService, }); return createSecurityRuleType({ - id: ML_ALERT_TYPE_ID, + id: ML_RULE_TYPE_ID, name: 'Machine Learning Rule', validate: { params: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts index 2f185853754b3..d5af7a4c8b5a4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.ts @@ -7,7 +7,7 @@ import { validateNonExact } from '@kbn/securitysolution-io-ts-utils'; import { PersistenceServices } from '../../../../../../rule_registry/server'; -import { QUERY_ALERT_TYPE_ID } from '../../../../../common/constants'; +import { QUERY_RULE_TYPE_ID } from '../../../../../common/constants'; import { queryRuleParams, QueryRuleParams } from '../../schemas/rule_schemas'; import { queryExecutor } from '../../signals/executors/query'; import { createSecurityRuleTypeFactory } from '../create_security_rule_type_factory'; @@ -33,7 +33,7 @@ export const createQueryAlertType = (createOptions: CreateRuleOptions) => { ruleDataService, }); return createSecurityRuleType({ - id: QUERY_ALERT_TYPE_ID, + id: QUERY_RULE_TYPE_ID, name: 'Custom Query Rule', validate: { params: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts index 34fb7bf5f8291..2c25134cc3760 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts @@ -8,7 +8,8 @@ import { CreateRulesOptions } from './types'; import { rulesClientMock } from '../../../../../alerting/server/mocks'; -export const getCreateRulesOptionsMock = (): CreateRulesOptions => ({ +export const getCreateRulesOptionsMock = (isRuleRegistryEnabled: boolean): CreateRulesOptions => ({ + isRuleRegistryEnabled, author: ['Elastic'], buildingBlockType: undefined, rulesClient: rulesClientMock.create(), @@ -61,7 +62,10 @@ export const getCreateRulesOptionsMock = (): CreateRulesOptions => ({ actions: [], }); -export const getCreateMlRulesOptionsMock = (): CreateRulesOptions => ({ +export const getCreateMlRulesOptionsMock = ( + isRuleRegistryEnabled: boolean +): CreateRulesOptions => ({ + isRuleRegistryEnabled, author: ['Elastic'], buildingBlockType: undefined, rulesClient: rulesClientMock.create(), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts index 3dd29977a8f2c..0fd708791712a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts @@ -8,9 +8,12 @@ import { createRules } from './create_rules'; import { getCreateMlRulesOptionsMock } from './create_rules.mock'; -describe('createRules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('createRules - %s', (_, isRuleRegistryEnabled) => { it('calls the rulesClient with legacy ML params', async () => { - const ruleOptions = getCreateMlRulesOptionsMock(); + const ruleOptions = getCreateMlRulesOptionsMock(isRuleRegistryEnabled); await createRules(ruleOptions); expect(ruleOptions.rulesClient.create).toHaveBeenCalledWith( expect.objectContaining({ @@ -26,7 +29,7 @@ describe('createRules', () => { it('calls the rulesClient with ML params', async () => { const ruleOptions = { - ...getCreateMlRulesOptionsMock(), + ...getCreateMlRulesOptionsMock(isRuleRegistryEnabled), machineLearningJobId: ['new_job_1', 'new_job_2'], }; await createRules(ruleOptions); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts index bc415a0de6961..bed6bf4303897 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts @@ -20,6 +20,7 @@ import { CreateRulesOptions } from './types'; import { addTags } from './add_tags'; import { PartialFilter, RuleTypeParams } from '../types'; import { transformToAlertThrottle, transformToNotifyWhen } from './utils'; +import { ruleTypeMappings } from '../signals/utils'; export const createRules = async ({ rulesClient, @@ -68,16 +69,18 @@ export const createRules = async ({ to, type, references, + namespace, note, version, exceptionsList, actions, + isRuleRegistryEnabled, }: CreateRulesOptions): Promise> => { const rule = await rulesClient.create({ data: { name, tags: addTags(tags, ruleId, immutable), - alertTypeId: SIGNALS_ID, + alertTypeId: isRuleRegistryEnabled ? ruleTypeMappings[type] : SIGNALS_ID, consumer: SERVER_APP_ID, params: { anomalyThreshold, @@ -125,6 +128,7 @@ export const createRules = async ({ to, type, references, + namespace, note, version, exceptionsList, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/duplicate_rule.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/duplicate_rule.test.ts index 92b4dcff61b35..c3f6b0fbead91 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/duplicate_rule.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/duplicate_rule.test.ts @@ -52,6 +52,7 @@ describe('duplicateRule', () => { query: 'process.args : "chmod"', filters: [], buildingBlockType: undefined, + namespace: undefined, note: undefined, timelineId: undefined, timelineTitle: undefined, @@ -99,6 +100,7 @@ describe('duplicateRule', () => { "license": "", "maxSignals": 100, "meta": undefined, + "namespace": undefined, "note": undefined, "outputIndex": ".siem-signals-default", "query": "process.args : \\"chmod\\"", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.test.ts index 1f91355d7cde2..0f7545c4df936 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.test.ts @@ -6,16 +6,38 @@ */ import { getFilter } from './find_rules'; -import { SIGNALS_ID } from '../../../../common/constants'; +import { + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, + SIGNALS_ID, +} from '../../../../common/constants'; + +const allAlertTypeIds = `(alert.attributes.alertTypeId: ${ML_RULE_TYPE_ID} + OR alert.attributes.alertTypeId: ${QUERY_RULE_TYPE_ID} + OR alert.attributes.alertTypeId: ${INDICATOR_RULE_TYPE_ID})`.replace(/[\n\r]/g, ''); describe('find_rules', () => { - test('it returns a full filter with an AND if sent down', () => { - expect(getFilter('alert.attributes.enabled: true')).toEqual( - `alert.attributes.alertTypeId: ${SIGNALS_ID} AND alert.attributes.enabled: true` - ); - }); + const fullFilterTestCases: Array<[boolean, string]> = [ + [false, `alert.attributes.alertTypeId: ${SIGNALS_ID} AND alert.attributes.enabled: true`], + [true, `${allAlertTypeIds} AND alert.attributes.enabled: true`], + ]; + const nullFilterTestCases: Array<[boolean, string]> = [ + [false, `alert.attributes.alertTypeId: ${SIGNALS_ID}`], + [true, allAlertTypeIds], + ]; + + test.each(fullFilterTestCases)( + 'it returns a full filter with an AND if sent down [rule registry enabled: %p]', + (isRuleRegistryEnabled, expected) => { + expect(getFilter('alert.attributes.enabled: true', isRuleRegistryEnabled)).toEqual(expected); + } + ); - test('it returns existing filter with no AND when not set', () => { - expect(getFilter(null)).toEqual(`alert.attributes.alertTypeId: ${SIGNALS_ID}`); - }); + test.each(nullFilterTestCases)( + 'it returns existing filter with no AND when not set [rule registry enabled: %p]', + (isRuleRegistryEnabled, expected) => { + expect(getFilter(null, isRuleRegistryEnabled)).toEqual(expected); + } + ); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.ts index e41dac066e18a..a1664f2e5a310 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/find_rules.ts @@ -8,13 +8,23 @@ import { FindResult } from '../../../../../alerting/server'; import { SIGNALS_ID } from '../../../../common/constants'; import { RuleParams } from '../schemas/rule_schemas'; +import { ruleTypeMappings } from '../signals/utils'; import { FindRuleOptions } from './types'; -export const getFilter = (filter: string | null | undefined) => { +export const getFilter = ( + filter: string | null | undefined, + isRuleRegistryEnabled: boolean = false +) => { + const alertTypeFilter = isRuleRegistryEnabled + ? `(${Object.values(ruleTypeMappings) + .map((type) => (type !== SIGNALS_ID ? `alert.attributes.alertTypeId: ${type}` : undefined)) + .filter((type) => type != null) + .join(' OR ')})` + : `alert.attributes.alertTypeId: ${SIGNALS_ID}`; if (filter == null) { - return `alert.attributes.alertTypeId: ${SIGNALS_ID}`; + return alertTypeFilter; } else { - return `alert.attributes.alertTypeId: ${SIGNALS_ID} AND ${filter}`; + return `${alertTypeFilter} AND ${filter}`; } }; @@ -26,13 +36,14 @@ export const findRules = ({ filter, sortField, sortOrder, + isRuleRegistryEnabled, }: FindRuleOptions): Promise> => { return rulesClient.find({ options: { fields, page, perPage, - filter: getFilter(filter), + filter: getFilter(filter, isRuleRegistryEnabled), sortOrder, sortField, }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.test.ts index 19a6a4e43d877..b478cc2df09a1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.test.ts @@ -20,7 +20,10 @@ import { getNonPackagedRulesCount, } from './get_existing_prepackaged_rules'; -describe('get_existing_prepackaged_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('get_existing_prepackaged_rules - %s', (_, isRuleRegistryEnabled) => { afterEach(() => { jest.resetAllMocks(); }); @@ -28,23 +31,23 @@ describe('get_existing_prepackaged_rules', () => { describe('getExistingPrepackagedRules', () => { test('should return a single item in a single page', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - const rules = await getExistingPrepackagedRules({ rulesClient }); - expect(rules).toEqual([getAlertMock(getQueryRuleParams())]); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + const rules = await getExistingPrepackagedRules({ isRuleRegistryEnabled, rulesClient }); + expect(rules).toEqual([getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())]); }); test('should return 3 items over 1 page with all on one page', async () => { const rulesClient = rulesClientMock.create(); - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.params.immutable = true; result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.params.immutable = true; result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; - const result3 = getAlertMock(getQueryRuleParams()); + const result3 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result3.params.immutable = true; result3.id = 'f3e1bf0b-b95f-43da-b1de-5d2f0af2287a'; @@ -68,7 +71,7 @@ describe('get_existing_prepackaged_rules', () => { }) ); - const rules = await getExistingPrepackagedRules({ rulesClient }); + const rules = await getExistingPrepackagedRules({ isRuleRegistryEnabled, rulesClient }); expect(rules).toEqual([result1, result2, result3]); }); }); @@ -76,18 +79,18 @@ describe('get_existing_prepackaged_rules', () => { describe('getNonPackagedRules', () => { test('should return a single item in a single page', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - const rules = await getNonPackagedRules({ rulesClient }); - expect(rules).toEqual([getAlertMock(getQueryRuleParams())]); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + const rules = await getNonPackagedRules({ isRuleRegistryEnabled, rulesClient }); + expect(rules).toEqual([getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())]); }); test('should return 2 items over 1 page', async () => { const rulesClient = rulesClientMock.create(); - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; // first result mock which is for returning the total @@ -105,20 +108,20 @@ describe('get_existing_prepackaged_rules', () => { getFindResultWithMultiHits({ data: [result1, result2], perPage: 2, page: 1, total: 2 }) ); - const rules = await getNonPackagedRules({ rulesClient }); + const rules = await getNonPackagedRules({ isRuleRegistryEnabled, rulesClient }); expect(rules).toEqual([result1, result2]); }); test('should return 3 items over 1 page with all on one page', async () => { const rulesClient = rulesClientMock.create(); - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; - const result3 = getAlertMock(getQueryRuleParams()); + const result3 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result3.id = 'f3e1bf0b-b95f-43da-b1de-5d2f0af2287a'; // first result mock which is for returning the total @@ -141,7 +144,7 @@ describe('get_existing_prepackaged_rules', () => { }) ); - const rules = await getNonPackagedRules({ rulesClient }); + const rules = await getNonPackagedRules({ isRuleRegistryEnabled, rulesClient }); expect(rules).toEqual([result1, result2, result3]); }); }); @@ -149,18 +152,18 @@ describe('get_existing_prepackaged_rules', () => { describe('getRules', () => { test('should return a single item in a single page', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - const rules = await getRules({ rulesClient, filter: '' }); - expect(rules).toEqual([getAlertMock(getQueryRuleParams())]); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + const rules = await getRules({ isRuleRegistryEnabled, rulesClient, filter: '' }); + expect(rules).toEqual([getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())]); }); test('should return 2 items over two pages, one per page', async () => { const rulesClient = rulesClientMock.create(); - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; // first result mock which is for returning the total @@ -178,7 +181,7 @@ describe('get_existing_prepackaged_rules', () => { getFindResultWithMultiHits({ data: [result1, result2], perPage: 2, page: 1, total: 2 }) ); - const rules = await getRules({ rulesClient, filter: '' }); + const rules = await getRules({ isRuleRegistryEnabled, rulesClient, filter: '' }); expect(rules).toEqual([result1, result2]); }); }); @@ -186,8 +189,8 @@ describe('get_existing_prepackaged_rules', () => { describe('getRulesCount', () => { test('it returns a count', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - const rules = await getRulesCount({ rulesClient, filter: '' }); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + const rules = await getRulesCount({ isRuleRegistryEnabled, rulesClient, filter: '' }); expect(rules).toEqual(1); }); }); @@ -195,8 +198,8 @@ describe('get_existing_prepackaged_rules', () => { describe('getNonPackagedRulesCount', () => { test('it returns a count', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); - const rules = await getNonPackagedRulesCount({ rulesClient }); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); + const rules = await getNonPackagedRulesCount({ isRuleRegistryEnabled, rulesClient }); expect(rules).toEqual(1); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.ts index be8bf1303846d..caa32a809b0a8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_existing_prepackaged_rules.ts @@ -14,21 +14,26 @@ export const FILTER_NON_PREPACKED_RULES = `alert.attributes.tags: "${INTERNAL_IM export const FILTER_PREPACKED_RULES = `alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:true"`; export const getNonPackagedRulesCount = async ({ + isRuleRegistryEnabled, rulesClient, }: { + isRuleRegistryEnabled: boolean; rulesClient: RulesClient; }): Promise => { - return getRulesCount({ rulesClient, filter: FILTER_NON_PREPACKED_RULES }); + return getRulesCount({ isRuleRegistryEnabled, rulesClient, filter: FILTER_NON_PREPACKED_RULES }); }; export const getRulesCount = async ({ rulesClient, filter, + isRuleRegistryEnabled, }: { rulesClient: RulesClient; filter: string; + isRuleRegistryEnabled: boolean; }): Promise => { const firstRule = await findRules({ + isRuleRegistryEnabled, rulesClient, filter, perPage: 1, @@ -43,12 +48,15 @@ export const getRulesCount = async ({ export const getRules = async ({ rulesClient, filter, + isRuleRegistryEnabled, }: { rulesClient: RulesClient; filter: string; -}): Promise => { - const count = await getRulesCount({ rulesClient, filter }); + isRuleRegistryEnabled: boolean; +}) => { + const count = await getRulesCount({ rulesClient, filter, isRuleRegistryEnabled }); const rules = await findRules({ + isRuleRegistryEnabled, rulesClient, filter, perPage: count, @@ -58,7 +66,7 @@ export const getRules = async ({ fields: undefined, }); - if (isAlertTypes(rules.data)) { + if (isAlertTypes(isRuleRegistryEnabled, rules.data)) { return rules.data; } else { // If this was ever true, you have a really messed up system. @@ -69,22 +77,28 @@ export const getRules = async ({ export const getNonPackagedRules = async ({ rulesClient, + isRuleRegistryEnabled, }: { rulesClient: RulesClient; + isRuleRegistryEnabled: boolean; }): Promise => { return getRules({ rulesClient, filter: FILTER_NON_PREPACKED_RULES, + isRuleRegistryEnabled, }); }; export const getExistingPrepackagedRules = async ({ rulesClient, + isRuleRegistryEnabled, }: { rulesClient: RulesClient; + isRuleRegistryEnabled: boolean; }): Promise => { return getRules({ rulesClient, filter: FILTER_PREPACKED_RULES, + isRuleRegistryEnabled, }); }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts index 2870bee99e51a..3ca5960d7d4e1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts @@ -16,11 +16,14 @@ import { getListArrayMock } from '../../../../common/detection_engine/schemas/ty import { getThreatMock } from '../../../../common/detection_engine/schemas/types/threat.mock'; import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; -describe('getExportAll', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('getExportAll - %s', (_, isRuleRegistryEnabled) => { test('it exports everything from the alerts client', async () => { const rulesClient = rulesClientMock.create(); - const result = getFindResultWithSingleHit(); - const alert = getAlertMock(getQueryRuleParams()); + const result = getFindResultWithSingleHit(isRuleRegistryEnabled); + const alert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); alert.params = { ...alert.params, filters: [{ query: { match_phrase: { 'host.name': 'some-host' } } }], @@ -32,7 +35,7 @@ describe('getExportAll', () => { result.data = [alert]; rulesClient.find.mockResolvedValue(result); - const exports = await getExportAll(rulesClient); + const exports = await getExportAll(rulesClient, isRuleRegistryEnabled); const rulesJson = JSON.parse(exports.rulesNdjson); const detailsJson = JSON.parse(exports.exportDetails); expect(rulesJson).toEqual({ @@ -94,7 +97,7 @@ describe('getExportAll', () => { rulesClient.find.mockResolvedValue(findResult); - const exports = await getExportAll(rulesClient); + const exports = await getExportAll(rulesClient, isRuleRegistryEnabled); expect(exports).toEqual({ rulesNdjson: '', exportDetails: '{"exported_count":0,"missing_rules":[],"missing_rules_count":0}\n', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts index 4a79f0089491f..f44471e6e26f9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts @@ -12,12 +12,13 @@ import { transformAlertsToRules } from '../routes/rules/utils'; import { transformDataToNdjson } from '../../../utils/read_stream/create_stream_from_ndjson'; export const getExportAll = async ( - rulesClient: RulesClient + rulesClient: RulesClient, + isRuleRegistryEnabled: boolean ): Promise<{ rulesNdjson: string; exportDetails: string; }> => { - const ruleAlertTypes = await getNonPackagedRules({ rulesClient }); + const ruleAlertTypes = await getNonPackagedRules({ rulesClient, isRuleRegistryEnabled }); const rules = transformAlertsToRules(ruleAlertTypes); // We do not support importing/exporting actions. When we do, delete this line of code const rulesWithoutActions = rules.map((rule) => ({ ...rule, actions: [] })); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts index f4325086e4212..740427e44b560 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts @@ -16,7 +16,10 @@ import { getListArrayMock } from '../../../../common/detection_engine/schemas/ty import { getThreatMock } from '../../../../common/detection_engine/schemas/types/threat.mock'; import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; -describe('get_export_by_object_ids', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('get_export_by_object_ids - %s', (_, isRuleRegistryEnabled) => { beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); @@ -25,10 +28,10 @@ describe('get_export_by_object_ids', () => { describe('getExportByObjectIds', () => { test('it exports object ids into an expected string with new line characters', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const objects = [{ rule_id: 'rule-1' }]; - const exports = await getExportByObjectIds(rulesClient, objects); + const exports = await getExportByObjectIds(rulesClient, objects, isRuleRegistryEnabled); const exportsObj = { rulesNdjson: JSON.parse(exports.rulesNdjson), exportDetails: JSON.parse(exports.exportDetails), @@ -85,7 +88,7 @@ describe('get_export_by_object_ids', () => { test('it does not export immutable rules', async () => { const rulesClient = rulesClientMock.create(); - const result = getAlertMock(getQueryRuleParams()); + const result = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result.params.immutable = true; const findResult: FindHit = { @@ -95,11 +98,11 @@ describe('get_export_by_object_ids', () => { data: [result], }; - rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); + rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); rulesClient.find.mockResolvedValue(findResult); const objects = [{ rule_id: 'rule-1' }]; - const exports = await getExportByObjectIds(rulesClient, objects); + const exports = await getExportByObjectIds(rulesClient, objects, isRuleRegistryEnabled); expect(exports).toEqual({ rulesNdjson: '', exportDetails: @@ -111,10 +114,10 @@ describe('get_export_by_object_ids', () => { describe('getRulesFromObjects', () => { test('it returns transformed rules from objects sent in', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const objects = [{ rule_id: 'rule-1' }]; - const exports = await getRulesFromObjects(rulesClient, objects); + const exports = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled); const expected: RulesErrors = { exportedCount: 1, missingRules: [], @@ -175,7 +178,7 @@ describe('get_export_by_object_ids', () => { test('it does not transform the rule if the rule is an immutable rule and designates it as a missing rule', async () => { const rulesClient = rulesClientMock.create(); - const result = getAlertMock(getQueryRuleParams()); + const result = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result.params.immutable = true; const findResult: FindHit = { @@ -189,7 +192,7 @@ describe('get_export_by_object_ids', () => { rulesClient.find.mockResolvedValue(findResult); const objects = [{ rule_id: 'rule-1' }]; - const exports = await getRulesFromObjects(rulesClient, objects); + const exports = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled); const expected: RulesErrors = { exportedCount: 0, missingRules: [{ rule_id: 'rule-1' }], @@ -212,7 +215,7 @@ describe('get_export_by_object_ids', () => { rulesClient.find.mockResolvedValue(findResult); const objects = [{ rule_id: 'rule-1' }]; - const exports = await getRulesFromObjects(rulesClient, objects); + const exports = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled); const expected: RulesErrors = { exportedCount: 0, missingRules: [{ rule_id: 'rule-1' }], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts index 812310bcb501a..31a7604306de7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts @@ -34,12 +34,13 @@ export interface RulesErrors { export const getExportByObjectIds = async ( rulesClient: RulesClient, - objects: Array<{ rule_id: string }> + objects: Array<{ rule_id: string }>, + isRuleRegistryEnabled: boolean ): Promise<{ rulesNdjson: string; exportDetails: string; }> => { - const rulesAndErrors = await getRulesFromObjects(rulesClient, objects); + const rulesAndErrors = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled); // We do not support importing/exporting actions. When we do, delete this line of code const rulesWithoutActions = rulesAndErrors.rules.map((rule) => ({ ...rule, actions: [] })); const rulesNdjson = transformDataToNdjson(rulesWithoutActions); @@ -49,7 +50,8 @@ export const getExportByObjectIds = async ( export const getRulesFromObjects = async ( rulesClient: RulesClient, - objects: Array<{ rule_id: string }> + objects: Array<{ rule_id: string }>, + isRuleRegistryEnabled: boolean ): Promise => { // If we put more than 1024 ids in one block like "alert.attributes.tags: (id1 OR id2 OR ... OR id1100)" // then the KQL -> ES DSL query generator still puts them all in the same "should" array, but ES defaults @@ -67,6 +69,7 @@ export const getRulesFromObjects = async ( }) .join(' OR '); const rules = await findRules({ + isRuleRegistryEnabled, rulesClient, filter, page: 1, @@ -79,7 +82,7 @@ export const getRulesFromObjects = async ( const matchingRule = rules.data.find((rule) => rule.params.ruleId === ruleId); if ( matchingRule != null && - isAlertType(matchingRule) && + isAlertType(isRuleRegistryEnabled, matchingRule) && matchingRule.params.immutable !== true ) { return { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.test.ts index 7482097aafd22..4ef84fd1619ea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.test.ts @@ -9,57 +9,61 @@ import { getRulesToInstall } from './get_rules_to_install'; import { getAlertMock } from '../routes/__mocks__/request_responses'; import { getAddPrepackagedRulesSchemaDecodedMock } from '../../../../common/detection_engine/schemas/request/add_prepackaged_rules_schema.mock'; import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; +import { AddPrepackagedRulesSchemaDecoded } from '../../../../common/detection_engine/schemas/request'; -describe('get_rules_to_install', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('get_rules_to_install - %s', (_, isRuleRegistryEnabled) => { test('should return empty array if both rule sets are empty', () => { const update = getRulesToInstall([], []); expect(update).toEqual([]); }); test('should return empty array if the two rule ids match', () => { - const ruleFromFileSystem = getAddPrepackagedRulesSchemaDecodedMock(); + const ruleFromFileSystem = getAddPrepackagedRulesSchemaDecodedMock() as AddPrepackagedRulesSchemaDecoded; ruleFromFileSystem.rule_id = 'rule-1'; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-1'; const update = getRulesToInstall([ruleFromFileSystem], [installedRule]); expect(update).toEqual([]); }); test('should return the rule to install if the id of the two rules do not match', () => { - const ruleFromFileSystem = getAddPrepackagedRulesSchemaDecodedMock(); + const ruleFromFileSystem = getAddPrepackagedRulesSchemaDecodedMock() as AddPrepackagedRulesSchemaDecoded; ruleFromFileSystem.rule_id = 'rule-1'; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-2'; const update = getRulesToInstall([ruleFromFileSystem], [installedRule]); expect(update).toEqual([ruleFromFileSystem]); }); test('should return two rules to install if both the ids of the two rules do not match', () => { - const ruleFromFileSystem1 = getAddPrepackagedRulesSchemaDecodedMock(); + const ruleFromFileSystem1 = getAddPrepackagedRulesSchemaDecodedMock() as AddPrepackagedRulesSchemaDecoded; ruleFromFileSystem1.rule_id = 'rule-1'; - const ruleFromFileSystem2 = getAddPrepackagedRulesSchemaDecodedMock(); + const ruleFromFileSystem2 = getAddPrepackagedRulesSchemaDecodedMock() as AddPrepackagedRulesSchemaDecoded; ruleFromFileSystem2.rule_id = 'rule-2'; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-3'; const update = getRulesToInstall([ruleFromFileSystem1, ruleFromFileSystem2], [installedRule]); expect(update).toEqual([ruleFromFileSystem1, ruleFromFileSystem2]); }); test('should return two rules of three to install if both the ids of the two rules do not match but the third does', () => { - const ruleFromFileSystem1 = getAddPrepackagedRulesSchemaDecodedMock(); + const ruleFromFileSystem1 = getAddPrepackagedRulesSchemaDecodedMock() as AddPrepackagedRulesSchemaDecoded; ruleFromFileSystem1.rule_id = 'rule-1'; - const ruleFromFileSystem2 = getAddPrepackagedRulesSchemaDecodedMock(); + const ruleFromFileSystem2 = getAddPrepackagedRulesSchemaDecodedMock() as AddPrepackagedRulesSchemaDecoded; ruleFromFileSystem2.rule_id = 'rule-2'; - const ruleFromFileSystem3 = getAddPrepackagedRulesSchemaDecodedMock(); + const ruleFromFileSystem3 = getAddPrepackagedRulesSchemaDecodedMock() as AddPrepackagedRulesSchemaDecoded; ruleFromFileSystem3.rule_id = 'rule-3'; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-3'; const update = getRulesToInstall( [ruleFromFileSystem1, ruleFromFileSystem2, ruleFromFileSystem3], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.ts index 65f3d4661cc4f..a9e22562606a9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_install.ts @@ -11,7 +11,7 @@ import { RuleAlertType } from './types'; export const getRulesToInstall = ( rulesFromFileSystem: AddPrepackagedRulesSchemaDecoded[], installedRules: RuleAlertType[] -): AddPrepackagedRulesSchemaDecoded[] => { +) => { return rulesFromFileSystem.filter( (rule) => !installedRules.some((installedRule) => installedRule.params.ruleId === rule.rule_id) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.test.ts index 163585e7594ab..dda3bf6efe44c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.test.ts @@ -10,7 +10,10 @@ import { getAlertMock } from '../routes/__mocks__/request_responses'; import { getAddPrepackagedRulesSchemaDecodedMock } from '../../../../common/detection_engine/schemas/request/add_prepackaged_rules_schema.mock'; import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; -describe('get_rules_to_update', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('get_rules_to_update - %s', (_, isRuleRegistryEnabled) => { describe('get_rules_to_update', () => { test('should return empty array if both rule sets are empty', () => { const update = getRulesToUpdate([], []); @@ -22,7 +25,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 2; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-2'; installedRule.params.version = 1; const update = getRulesToUpdate([ruleFromFileSystem], [installedRule]); @@ -34,7 +37,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 1; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-1'; installedRule.params.version = 2; const update = getRulesToUpdate([ruleFromFileSystem], [installedRule]); @@ -46,7 +49,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 1; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-1'; installedRule.params.version = 1; const update = getRulesToUpdate([ruleFromFileSystem], [installedRule]); @@ -58,7 +61,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 2; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-1'; installedRule.params.version = 1; installedRule.params.exceptionsList = []; @@ -72,12 +75,12 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = []; - const installedRule2 = getAlertMock(getQueryRuleParams()); + const installedRule2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule2.params.ruleId = 'rule-2'; installedRule2.params.version = 1; installedRule2.params.exceptionsList = []; @@ -95,12 +98,12 @@ describe('get_rules_to_update', () => { ruleFromFileSystem2.rule_id = 'rule-2'; ruleFromFileSystem2.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = []; - const installedRule2 = getAlertMock(getQueryRuleParams()); + const installedRule2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule2.params.ruleId = 'rule-2'; installedRule2.params.version = 1; installedRule2.params.exceptionsList = []; @@ -125,7 +128,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = []; @@ -147,7 +150,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ @@ -179,7 +182,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ @@ -201,7 +204,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ @@ -228,7 +231,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem2.rule_id = 'rule-2'; ruleFromFileSystem2.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ @@ -239,7 +242,7 @@ describe('get_rules_to_update', () => { type: 'endpoint', }, ]; - const installedRule2 = getAlertMock(getQueryRuleParams()); + const installedRule2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule2.params.ruleId = 'rule-2'; installedRule2.params.version = 1; installedRule2.params.exceptionsList = [ @@ -278,7 +281,7 @@ describe('get_rules_to_update', () => { }, ]; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ @@ -290,7 +293,7 @@ describe('get_rules_to_update', () => { }, ]; - const installedRule2 = getAlertMock(getQueryRuleParams()); + const installedRule2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule2.params.ruleId = 'rule-2'; installedRule2.params.version = 1; installedRule2.params.exceptionsList = [ @@ -320,7 +323,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 2; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-2'; installedRule.params.version = 1; const shouldUpdate = filterInstalledRules(ruleFromFileSystem, [installedRule]); @@ -332,7 +335,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 1; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-1'; installedRule.params.version = 2; const shouldUpdate = filterInstalledRules(ruleFromFileSystem, [installedRule]); @@ -344,7 +347,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 1; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-1'; installedRule.params.version = 1; const shouldUpdate = filterInstalledRules(ruleFromFileSystem, [installedRule]); @@ -356,7 +359,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem.rule_id = 'rule-1'; ruleFromFileSystem.version = 2; - const installedRule = getAlertMock(getQueryRuleParams()); + const installedRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule.params.ruleId = 'rule-1'; installedRule.params.version = 1; installedRule.params.exceptionsList = []; @@ -380,7 +383,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = []; @@ -402,7 +405,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ @@ -434,7 +437,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ @@ -456,7 +459,7 @@ describe('get_rules_to_update', () => { ruleFromFileSystem1.rule_id = 'rule-1'; ruleFromFileSystem1.version = 2; - const installedRule1 = getAlertMock(getQueryRuleParams()); + const installedRule1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); installedRule1.params.ruleId = 'rule-1'; installedRule1.params.version = 1; installedRule1.params.exceptionsList = [ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.ts index 7e098a28552a0..f0017c5e4bdb6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_rules_to_update.ts @@ -18,7 +18,7 @@ import { RuleAlertType } from './types'; export const getRulesToUpdate = ( rulesFromFileSystem: AddPrepackagedRulesSchemaDecoded[], installedRules: RuleAlertType[] -): AddPrepackagedRulesSchemaDecoded[] => { +) => { return rulesFromFileSystem .filter((ruleFromFileSystem) => filterInstalledRules(ruleFromFileSystem, installedRules)) .map((ruleFromFileSystem) => mergeExceptionLists(ruleFromFileSystem, installedRules)); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/install_prepacked_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/install_prepacked_rules.ts index 1681ac7f1659f..3f7191a970020 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/install_prepacked_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/install_prepacked_rules.ts @@ -14,7 +14,8 @@ import { PartialFilter } from '../types'; export const installPrepackagedRules = ( rulesClient: RulesClient, rules: AddPrepackagedRulesSchemaDecoded[], - outputIndex: string + outputIndex: string, + isRuleRegistryEnabled: boolean ): Array>> => rules.reduce>>>((acc, rule) => { const { @@ -60,6 +61,7 @@ export const installPrepackagedRules = ( threshold, timestamp_override: timestampOverride, references, + namespace, note, version, exceptions_list: exceptionsList, @@ -70,6 +72,7 @@ export const installPrepackagedRules = ( return [ ...acc, createRules({ + isRuleRegistryEnabled, rulesClient, anomalyThreshold, author, @@ -116,6 +119,7 @@ export const installPrepackagedRules = ( throttle: null, // At this time there is no pre-packaged actions timestampOverride, references, + namespace, note, version, exceptionsList, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.mock.ts index 9ebec947bcc0e..1d09e4ca5c508 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.mock.ts @@ -11,7 +11,7 @@ import { getAlertMock } from '../routes/__mocks__/request_responses'; import { getMlRuleParams, getQueryRuleParams } from '../schemas/rule_schemas.mock'; import { ruleExecutionLogClientMock } from '../rule_execution_log/__mocks__/rule_execution_log_client'; -export const getPatchRulesOptionsMock = (): PatchRulesOptions => ({ +export const getPatchRulesOptionsMock = (isRuleRegistryEnabled: boolean): PatchRulesOptions => ({ author: ['Elastic'], buildingBlockType: undefined, rulesClient: rulesClientMock.create(), @@ -61,10 +61,10 @@ export const getPatchRulesOptionsMock = (): PatchRulesOptions => ({ version: 1, exceptionsList: [], actions: [], - rule: getAlertMock(getQueryRuleParams()), + rule: getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), }); -export const getPatchMlRulesOptionsMock = (): PatchRulesOptions => ({ +export const getPatchMlRulesOptionsMock = (isRuleRegistryEnabled: boolean): PatchRulesOptions => ({ author: ['Elastic'], buildingBlockType: undefined, rulesClient: rulesClientMock.create(), @@ -114,5 +114,5 @@ export const getPatchMlRulesOptionsMock = (): PatchRulesOptions => ({ version: 1, exceptionsList: [], actions: [], - rule: getAlertMock(getMlRuleParams()), + rule: getAlertMock(isRuleRegistryEnabled, getMlRuleParams()), }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.test.ts index dbfc1427abf95..ee39120a8b6d0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.test.ts @@ -12,15 +12,18 @@ import { RulesClientMock } from '../../../../../alerting/server/rules_client.moc import { getAlertMock } from '../routes/__mocks__/request_responses'; import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; -describe('patchRules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('patchRules - %s', (_, isRuleRegistryEnabled) => { it('should call rulesClient.disable if the rule was enabled and enabled is false', async () => { - const rulesOptionsMock = getPatchRulesOptionsMock(); + const rulesOptionsMock = getPatchRulesOptionsMock(isRuleRegistryEnabled); const ruleOptions: PatchRulesOptions = { ...rulesOptionsMock, enabled: false, }; ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await patchRules(ruleOptions); expect(ruleOptions.rulesClient.disable).toHaveBeenCalledWith( @@ -31,7 +34,7 @@ describe('patchRules', () => { }); it('should call rulesClient.enable if the rule was disabled and enabled is true', async () => { - const rulesOptionsMock = getPatchRulesOptionsMock(); + const rulesOptionsMock = getPatchRulesOptionsMock(isRuleRegistryEnabled); const ruleOptions: PatchRulesOptions = { ...rulesOptionsMock, enabled: true, @@ -40,7 +43,7 @@ describe('patchRules', () => { ruleOptions.rule.enabled = false; } ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await patchRules(ruleOptions); expect(ruleOptions.rulesClient.enable).toHaveBeenCalledWith( @@ -51,7 +54,7 @@ describe('patchRules', () => { }); it('calls the rulesClient with legacy ML params', async () => { - const rulesOptionsMock = getPatchMlRulesOptionsMock(); + const rulesOptionsMock = getPatchMlRulesOptionsMock(isRuleRegistryEnabled); const ruleOptions: PatchRulesOptions = { ...rulesOptionsMock, enabled: true, @@ -60,7 +63,7 @@ describe('patchRules', () => { ruleOptions.rule.enabled = false; } ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await patchRules(ruleOptions); expect(ruleOptions.rulesClient.update).toHaveBeenCalledWith( @@ -76,7 +79,7 @@ describe('patchRules', () => { }); it('calls the rulesClient with new ML params', async () => { - const rulesOptionsMock = getPatchMlRulesOptionsMock(); + const rulesOptionsMock = getPatchMlRulesOptionsMock(isRuleRegistryEnabled); const ruleOptions: PatchRulesOptions = { ...rulesOptionsMock, machineLearningJobId: ['new_job_1', 'new_job_2'], @@ -86,7 +89,7 @@ describe('patchRules', () => { ruleOptions.rule.enabled = false; } ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await patchRules(ruleOptions); expect(ruleOptions.rulesClient.update).toHaveBeenCalledWith( @@ -103,7 +106,7 @@ describe('patchRules', () => { describe('regression tests', () => { it("updates the rule's actions if provided", async () => { - const rulesOptionsMock = getPatchRulesOptionsMock(); + const rulesOptionsMock = getPatchRulesOptionsMock(isRuleRegistryEnabled); const ruleOptions: PatchRulesOptions = { ...rulesOptionsMock, actions: [ @@ -118,7 +121,7 @@ describe('patchRules', () => { ], }; ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await patchRules(ruleOptions); expect(ruleOptions.rulesClient.update).toHaveBeenCalledWith( @@ -140,7 +143,7 @@ describe('patchRules', () => { }); it('does not update actions if none are specified', async () => { - const ruleOptions = getPatchRulesOptionsMock(); + const ruleOptions = getPatchRulesOptionsMock(isRuleRegistryEnabled); delete ruleOptions.actions; if (ruleOptions.rule != null) { ruleOptions.rule.actions = [ @@ -155,7 +158,7 @@ describe('patchRules', () => { ]; } ((ruleOptions.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await patchRules(ruleOptions); expect(ruleOptions.rulesClient.update).toHaveBeenCalledWith( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts index bc1faa5dff470..c3b7e7288dc57 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts @@ -80,6 +80,7 @@ export const patchRules = async ({ to, type, references, + namespace, note, version, exceptionsList, @@ -131,6 +132,7 @@ export const patchRules = async ({ type, references, version, + namespace, note, exceptionsList, anomalyThreshold, @@ -176,6 +178,7 @@ export const patchRules = async ({ to, type, references, + namespace, note, version: calculatedVersion, exceptionsList, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.test.ts index 33bc002942497..6f89d725a458e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.test.ts @@ -21,7 +21,10 @@ export class TestError extends Error { public output: { statusCode: number }; } -describe('read_rules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('read_rules - %s', (_, isRuleRegistryEnabled) => { beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); @@ -30,23 +33,25 @@ describe('read_rules', () => { describe('readRules', () => { test('should return the output from rulesClient if id is set but ruleId is undefined', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); + rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', ruleId: undefined, }); - expect(rule).toEqual(getAlertMock(getQueryRuleParams())); + expect(rule).toEqual(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); }); test('should return null if saved object found by alerts client given id is not alert type', async () => { const rulesClient = rulesClientMock.create(); - const result = getAlertMock(getQueryRuleParams()); + const result = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); // @ts-expect-error delete result.alertTypeId; rulesClient.get.mockResolvedValue(result); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', ruleId: undefined, @@ -61,6 +66,7 @@ describe('read_rules', () => { }); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', ruleId: undefined, @@ -75,6 +81,7 @@ describe('read_rules', () => { }); try { await readRules({ + isRuleRegistryEnabled, rulesClient, id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', ruleId: undefined, @@ -86,23 +93,25 @@ describe('read_rules', () => { test('should return the output from rulesClient if id is undefined but ruleId is set', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, id: undefined, ruleId: 'rule-1', }); - expect(rule).toEqual(getAlertMock(getQueryRuleParams())); + expect(rule).toEqual(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); }); test('should return null if the output from rulesClient with ruleId set is empty', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); + rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); rulesClient.find.mockResolvedValue({ data: [], page: 0, perPage: 1, total: 0 }); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, id: undefined, ruleId: 'rule-1', @@ -112,23 +121,25 @@ describe('read_rules', () => { test('should return the output from rulesClient if id is null but ruleId is set', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, id: undefined, ruleId: 'rule-1', }); - expect(rule).toEqual(getAlertMock(getQueryRuleParams())); + expect(rule).toEqual(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); }); test('should return null if id and ruleId are undefined', async () => { const rulesClient = rulesClientMock.create(); - rulesClient.get.mockResolvedValue(getAlertMock(getQueryRuleParams())); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); const rule = await readRules({ + isRuleRegistryEnabled, rulesClient, id: undefined, ruleId: undefined, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.ts index 141977f2474e0..9578e3d4cb6d2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/read_rules.ts @@ -20,6 +20,7 @@ import { isAlertType, ReadRuleOptions } from './types'; * a filter query against the tags using `alert.attributes.tags: "__internal:${ruleId}"]` */ export const readRules = async ({ + isRuleRegistryEnabled, rulesClient, id, ruleId, @@ -27,7 +28,7 @@ export const readRules = async ({ if (id != null) { try { const rule = await rulesClient.get({ id }); - if (isAlertType(rule)) { + if (isAlertType(isRuleRegistryEnabled, rule)) { return rule; } else { return null; @@ -42,6 +43,7 @@ export const readRules = async ({ } } else if (ruleId != null) { const ruleFromFind = await findRules({ + isRuleRegistryEnabled, rulesClient, filter: `alert.attributes.tags: "${INTERNAL_RULE_ID_KEY}:${ruleId}"`, page: 1, @@ -50,7 +52,10 @@ export const readRules = async ({ sortField: undefined, sortOrder: undefined, }); - if (ruleFromFind.data.length === 0 || !isAlertType(ruleFromFind.data[0])) { + if ( + ruleFromFind.data.length === 0 || + !isAlertType(isRuleRegistryEnabled, ruleFromFind.data[0]) + ) { return null; } else { return ruleFromFind.data[0]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts index 235217761c8b1..c27caaed5449e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts @@ -101,6 +101,7 @@ import { BuildingBlockTypeOrUndefined, RuleNameOverrideOrUndefined, EventCategoryOverrideOrUndefined, + NamespaceOrUndefined, } from '../../../../common/detection_engine/schemas/common/schemas'; import { RulesClient, PartialAlert } from '../../../../../alerting/server'; @@ -109,6 +110,7 @@ import { SIGNALS_ID } from '../../../../common/constants'; import { PartialFilter } from '../types'; import { RuleParams } from '../schemas/rule_schemas'; import { IRuleExecutionLogClient } from '../rule_execution_log/types'; +import { ruleTypeMappings } from '../signals/utils'; export type RuleAlertType = Alert; @@ -192,15 +194,20 @@ export interface Clients { } export const isAlertTypes = ( + isRuleRegistryEnabled: boolean, partialAlert: Array> ): partialAlert is RuleAlertType[] => { - return partialAlert.every((rule) => isAlertType(rule)); + return partialAlert.every((rule) => isAlertType(isRuleRegistryEnabled, rule)); }; export const isAlertType = ( + isRuleRegistryEnabled: boolean, partialAlert: PartialAlert ): partialAlert is RuleAlertType => { - return partialAlert.alertTypeId === SIGNALS_ID; + const ruleTypeValues = (Object.values(ruleTypeMappings) as unknown) as string[]; + return isRuleRegistryEnabled + ? ruleTypeValues.includes(partialAlert.alertTypeId as string) + : partialAlert.alertTypeId === SIGNALS_ID; }; export const isRuleStatusSavedObjectType = ( @@ -266,9 +273,12 @@ export interface CreateRulesOptions { version: Version; exceptionsList: ListArray; actions: RuleAlertAction[]; + isRuleRegistryEnabled: boolean; + namespace?: NamespaceOrUndefined; } export interface UpdateRulesOptions { + isRuleRegistryEnabled: boolean; spaceId: string; ruleStatusClient: IRuleExecutionLogClient; rulesClient: RulesClient; @@ -327,9 +337,11 @@ export interface PatchRulesOptions { exceptionsList: ListArrayOrUndefined; actions: RuleAlertAction[] | undefined; rule: SanitizedAlert | null; + namespace?: NamespaceOrUndefined; } export interface ReadRuleOptions { + isRuleRegistryEnabled: boolean; rulesClient: RulesClient; id: IdOrUndefined; ruleId: RuleIdOrUndefined; @@ -343,6 +355,7 @@ export interface DeleteRuleOptions { } export interface FindRuleOptions { + isRuleRegistryEnabled: boolean; rulesClient: RulesClient; perPage: PerPageOrUndefined; page: PageOrUndefined; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts index 5cc7f068aa06d..7c9f0c9ec67a3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts @@ -13,7 +13,10 @@ import { getAddPrepackagedRulesSchemaDecodedMock } from '../../../../common/dete import { ruleExecutionLogClientMock } from '../rule_execution_log/__mocks__/rule_execution_log_client'; jest.mock('./patch_rules'); -describe('updatePrepackagedRules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('updatePrepackagedRules - %s', (_, isRuleRegistryEnabled) => { let rulesClient: ReturnType; let ruleStatusClient: ReturnType; @@ -33,14 +36,15 @@ describe('updatePrepackagedRules', () => { ]; const outputIndex = 'outputIndex'; const prepackagedRule = getAddPrepackagedRulesSchemaDecodedMock(); - rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); await updatePrepackagedRules( rulesClient, 'default', ruleStatusClient, [{ ...prepackagedRule, actions }], - outputIndex + outputIndex, + isRuleRegistryEnabled ); expect(patchRules).toHaveBeenCalledWith( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.ts index fcfab2fda1a8b..d9c2ecd1b5732 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.ts @@ -54,7 +54,8 @@ export const updatePrepackagedRules = async ( spaceId: string, ruleStatusClient: IRuleExecutionLogClient, rules: AddPrepackagedRulesSchemaDecoded[], - outputIndex: string + outputIndex: string, + isRuleRegistryEnabled: boolean ): Promise => { const ruleChunks = chunk(UPDATE_CHUNK_SIZE, rules); for (const ruleChunk of ruleChunks) { @@ -63,7 +64,8 @@ export const updatePrepackagedRules = async ( spaceId, ruleStatusClient, ruleChunk, - outputIndex + outputIndex, + isRuleRegistryEnabled ); await Promise.all(rulePromises); } @@ -83,7 +85,8 @@ export const createPromises = ( spaceId: string, ruleStatusClient: IRuleExecutionLogClient, rules: AddPrepackagedRulesSchemaDecoded[], - outputIndex: string + outputIndex: string, + isRuleRegistryEnabled: boolean ): Array | null>> => { return rules.map(async (rule) => { const { @@ -133,7 +136,12 @@ export const createPromises = ( exceptions_list: exceptionsList, } = rule; - const existingRule = await readRules({ rulesClient, ruleId, id: undefined }); + const existingRule = await readRules({ + isRuleRegistryEnabled, + rulesClient, + ruleId, + id: undefined, + }); // TODO: Fix these either with an is conversion or by better typing them within io-ts const filters: PartialFilter[] | undefined = filtersObject as PartialFilter[]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.mock.ts index df9431e00a67c..58d6cf1fd5e6b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.mock.ts @@ -11,20 +11,21 @@ import { getUpdateRulesSchemaMock, } from '../../../../common/detection_engine/schemas/request/rule_schemas.mock'; import { ruleExecutionLogClientMock } from '../rule_execution_log/__mocks__/rule_execution_log_client'; -import { UpdateRulesOptions } from './types'; -export const getUpdateRulesOptionsMock = (): UpdateRulesOptions => ({ +export const getUpdateRulesOptionsMock = (isRuleRegistryEnabled: boolean) => ({ spaceId: 'default', rulesClient: rulesClientMock.create(), ruleStatusClient: ruleExecutionLogClientMock.create(), defaultOutputIndex: '.siem-signals-default', ruleUpdate: getUpdateRulesSchemaMock(), + isRuleRegistryEnabled, }); -export const getUpdateMlRulesOptionsMock = (): UpdateRulesOptions => ({ +export const getUpdateMlRulesOptionsMock = (isRuleRegistryEnabled: boolean) => ({ spaceId: 'default', rulesClient: rulesClientMock.create(), ruleStatusClient: ruleExecutionLogClientMock.create(), defaultOutputIndex: '.siem-signals-default', ruleUpdate: getUpdateMachineLearningSchemaMock(), + isRuleRegistryEnabled, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.test.ts index e46b4fad63a92..1ad5cd7ae934c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.test.ts @@ -11,15 +11,18 @@ import { getUpdateRulesOptionsMock, getUpdateMlRulesOptionsMock } from './update import { RulesClientMock } from '../../../../../alerting/server/rules_client.mock'; import { getMlRuleParams, getQueryRuleParams } from '../schemas/rule_schemas.mock'; -describe('updateRules', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('updateRules - %s', (_, isRuleRegistryEnabled) => { it('should call rulesClient.disable if the rule was enabled and enabled is false', async () => { - const rulesOptionsMock = getUpdateRulesOptionsMock(); + const rulesOptionsMock = getUpdateRulesOptionsMock(isRuleRegistryEnabled); rulesOptionsMock.ruleUpdate.enabled = false; ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).get.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await updateRules(rulesOptionsMock); @@ -32,15 +35,15 @@ describe('updateRules', () => { }); it('should call rulesClient.enable if the rule was disabled and enabled is true', async () => { - const rulesOptionsMock = getUpdateRulesOptionsMock(); + const rulesOptionsMock = getUpdateRulesOptionsMock(isRuleRegistryEnabled); rulesOptionsMock.ruleUpdate.enabled = true; ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).get.mockResolvedValue({ - ...getAlertMock(getQueryRuleParams()), + ...getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()), enabled: false, }); ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getQueryRuleParams()) + getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); await updateRules(rulesOptionsMock); @@ -53,15 +56,15 @@ describe('updateRules', () => { }); it('calls the rulesClient with params', async () => { - const rulesOptionsMock = getUpdateMlRulesOptionsMock(); + const rulesOptionsMock = getUpdateMlRulesOptionsMock(isRuleRegistryEnabled); rulesOptionsMock.ruleUpdate.enabled = true; ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).update.mockResolvedValue( - getAlertMock(getMlRuleParams()) + getAlertMock(isRuleRegistryEnabled, getMlRuleParams()) ); ((rulesOptionsMock.rulesClient as unknown) as RulesClientMock).get.mockResolvedValue( - getAlertMock(getMlRuleParams()) + getAlertMock(isRuleRegistryEnabled, getMlRuleParams()) ); await updateRules(rulesOptionsMock); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts index a3e0ba31f0c3c..f4060f7f831a9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts @@ -14,11 +14,12 @@ import { readRules } from './read_rules'; import { UpdateRulesOptions } from './types'; import { addTags } from './add_tags'; import { typeSpecificSnakeToCamel } from '../schemas/rule_converters'; -import { InternalRuleUpdate, RuleParams } from '../schemas/rule_schemas'; +import { RuleParams } from '../schemas/rule_schemas'; import { enableRule } from './enable_rule'; import { maybeMute, transformToAlertThrottle, transformToNotifyWhen } from './utils'; export const updateRules = async ({ + isRuleRegistryEnabled, spaceId, rulesClient, ruleStatusClient, @@ -26,6 +27,7 @@ export const updateRules = async ({ ruleUpdate, }: UpdateRulesOptions): Promise | null> => { const existingRule = await readRules({ + isRuleRegistryEnabled, rulesClient, ruleId: ruleUpdate.rule_id, id: ruleUpdate.id, @@ -36,7 +38,7 @@ export const updateRules = async ({ const typeSpecificParams = typeSpecificSnakeToCamel(ruleUpdate); const enabled = ruleUpdate.enabled ?? true; - const newInternalRule: InternalRuleUpdate = { + const newInternalRule = { name: ruleUpdate.name, tags: addTags(ruleUpdate.tags ?? [], existingRule.params.ruleId, existingRule.params.immutable), params: { @@ -63,6 +65,7 @@ export const updateRules = async ({ timestampOverride: ruleUpdate.timestamp_override, to: ruleUpdate.to ?? 'now', references: ruleUpdate.references ?? [], + namespace: ruleUpdate.namespace, note: ruleUpdate.note, // Always use the version from the request if specified. If it isn't specified, leave immutable rules alone and // increment the version of mutable rules by 1. diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts index 602e422772711..95e8552c4b14b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts @@ -81,6 +81,7 @@ describe('utils', () => { type: undefined, references: undefined, version: undefined, + namespace: undefined, note: undefined, anomalyThreshold: undefined, machineLearningJobId: undefined, @@ -131,6 +132,7 @@ describe('utils', () => { type: undefined, references: undefined, version: undefined, + namespace: undefined, note: undefined, anomalyThreshold: undefined, machineLearningJobId: undefined, @@ -181,6 +183,7 @@ describe('utils', () => { type: undefined, references: undefined, version: undefined, + namespace: undefined, note: undefined, anomalyThreshold: undefined, machineLearningJobId: undefined, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts index d9d5151a64c46..3fdd97b7d933f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts @@ -52,6 +52,7 @@ import { RuleNameOverrideOrUndefined, TimestampOverrideOrUndefined, EventCategoryOverrideOrUndefined, + NamespaceOrUndefined, } from '../../../../common/detection_engine/schemas/common/schemas'; import { PartialFilter } from '../types'; import { RuleParams } from '../schemas/rule_schemas'; @@ -118,6 +119,7 @@ export interface UpdateProperties { version: VersionOrUndefined; exceptionsList: ListArrayOrUndefined; anomalyThreshold: AnomalyThresholdOrUndefined; + namespace: NamespaceOrUndefined; } export const calculateVersion = ( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_converters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_converters.ts index 8a67636c6649d..5214be513a0e6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_converters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_converters.ts @@ -36,6 +36,7 @@ import { transformToAlertThrottle, transformToNotifyWhen, } from '../rules/utils'; +import { ruleTypeMappings } from '../signals/utils'; // These functions provide conversions from the request API schema to the internal rule schema and from the internal rule schema // to the response API schema. This provides static type-check assurances that the internal schema is in sync with the API schema for @@ -121,14 +122,15 @@ export const typeSpecificSnakeToCamel = (params: CreateTypeSpecific): TypeSpecif export const convertCreateAPIToInternalSchema = ( input: CreateRulesSchema, - siemClient: AppClient + siemClient: AppClient, + isRuleRegistryEnabled: boolean ): InternalRuleCreate => { const typeSpecificParams = typeSpecificSnakeToCamel(input); const newRuleId = input.rule_id ?? uuid.v4(); return { name: input.name, tags: addTags(input.tags ?? [], newRuleId, false), - alertTypeId: SIGNALS_ID, + alertTypeId: isRuleRegistryEnabled ? ruleTypeMappings[input.type] : SIGNALS_ID, consumer: SERVER_APP_ID, params: { author: input.author ?? [], @@ -153,6 +155,7 @@ export const convertCreateAPIToInternalSchema = ( timestampOverride: input.timestamp_override, to: input.to ?? 'now', references: input.references ?? [], + namespace: input.namespace, note: input.note, version: input.version ?? 1, exceptionsList: input.exceptions_list ?? [], @@ -249,6 +252,7 @@ export const commonParamsCamelToSnake = (params: BaseRuleParams) => { risk_score: params.riskScore, severity: params.severity, building_block_type: params.buildingBlockType, + namespace: params.namespace, note: params.note, license: params.license, output_index: params.outputIndex, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.mock.ts index 846a4e26410a3..506f40af2ee79 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.mock.ts @@ -36,6 +36,7 @@ const getBaseRuleParams = (): BaseRuleParams => { riskScoreMapping: [], ruleNameOverride: undefined, maxSignals: 10000, + namespace: undefined, note: '# Investigative notes', timelineId: 'some-timeline-id', timelineTitle: 'some-timeline-title', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.ts index c414ecc8655a3..e9215084614c0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/schemas/rule_schemas.ts @@ -32,6 +32,7 @@ import { buildingBlockTypeOrUndefined, description, enabled, + namespaceOrUndefined, noteOrUndefined, false_positives, rule_id, @@ -62,7 +63,13 @@ import { updated_at, } from '../../../../common/detection_engine/schemas/common/schemas'; -import { SIGNALS_ID, SERVER_APP_ID } from '../../../../common/constants'; +import { + SIGNALS_ID, + SERVER_APP_ID, + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, +} from '../../../../common/constants'; const nonEqlLanguages = t.keyof({ kuery: null, lucene: null }); export const baseRuleParams = t.exact( @@ -70,6 +77,7 @@ export const baseRuleParams = t.exact( author, buildingBlockType: buildingBlockTypeOrUndefined, description, + namespace: namespaceOrUndefined, note: noteOrUndefined, falsePositives: false_positives, from, @@ -196,10 +204,21 @@ export const notifyWhen = t.union([ t.null, ]); +export const allRuleTypes = t.union([ + t.literal(SIGNALS_ID), + // t.literal(EQL_RULE_TYPE_ID), + t.literal(ML_RULE_TYPE_ID), + t.literal(QUERY_RULE_TYPE_ID), + // t.literal(SAVED_QUERY_RULE_TYPE_ID), + t.literal(INDICATOR_RULE_TYPE_ID), + // t.literal(THRESHOLD_RULE_TYPE_ID), +]); +export type AllRuleTypes = t.TypeOf; + export const internalRuleCreate = t.type({ name, tags, - alertTypeId: t.literal(SIGNALS_ID), + alertTypeId: allRuleTypes, consumer: t.literal(SERVER_APP_ID), schedule: t.type({ interval: t.string, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts index 8037a9a201510..52b0799f5fe33 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts @@ -182,7 +182,7 @@ export const searchAfterAndBulkCreate = async ({ break; } } catch (exc: unknown) { - logger.error(buildRuleMessage(`[-] search_after and bulk threw an error ${exc}`)); + logger.error(buildRuleMessage(`[-] search_after_bulk_create threw an error ${exc}`)); return mergeReturns([ toReturn, createSearchAfterReturnType({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts index 9af8680ec726a..2696d6981083e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts @@ -177,7 +177,7 @@ describe('signal_rule_alert_type', () => { alertServices.scopedClusterClient.asCurrentUser.fieldCaps.mockResolvedValue( value as ApiResponse ); - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(false, getQueryRuleParams()); alertServices.savedObjectsClient.get.mockResolvedValue({ id: 'id', type: 'type', @@ -245,7 +245,7 @@ describe('signal_rule_alert_type', () => { }, application: {}, }); - const newRuleAlert = getAlertMock(getQueryRuleParams()); + const newRuleAlert = getAlertMock(false, getQueryRuleParams()); newRuleAlert.params.index = ['some*', 'myfa*', 'anotherindex*']; payload = getPayload(newRuleAlert, alertServices) as jest.Mocked; @@ -274,7 +274,7 @@ describe('signal_rule_alert_type', () => { }, application: {}, }); - const newRuleAlert = getAlertMock(getQueryRuleParams()); + const newRuleAlert = getAlertMock(false, getQueryRuleParams()); newRuleAlert.params.index = ['some*', 'myfa*', 'anotherindex*']; payload = getPayload(newRuleAlert, alertServices) as jest.Mocked; @@ -309,7 +309,7 @@ describe('signal_rule_alert_type', () => { }); it('should call scheduleActions if signalsCount was greater than 0 and rule has actions defined', async () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(false, getQueryRuleParams()); ruleAlert.actions = [ { actionTypeId: '.slack', @@ -333,7 +333,7 @@ describe('signal_rule_alert_type', () => { }); it('should resolve results_link when meta is an empty object to use "/app/security"', async () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(false, getQueryRuleParams()); ruleAlert.params.meta = {}; ruleAlert.actions = [ { @@ -366,7 +366,7 @@ describe('signal_rule_alert_type', () => { }); it('should resolve results_link when meta is undefined use "/app/security"', async () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(false, getQueryRuleParams()); delete ruleAlert.params.meta; ruleAlert.actions = [ { @@ -399,7 +399,7 @@ describe('signal_rule_alert_type', () => { }); it('should resolve results_link with a custom link', async () => { - const ruleAlert = getAlertMock(getQueryRuleParams()); + const ruleAlert = getAlertMock(false, getQueryRuleParams()); ruleAlert.params.meta = { kibana_siem_app_url: 'http://localhost' }; ruleAlert.actions = [ { @@ -433,7 +433,7 @@ describe('signal_rule_alert_type', () => { describe('ML rule', () => { it('should not call checkPrivileges if ML rule', async () => { - const ruleAlert = getAlertMock(getMlRuleParams()); + const ruleAlert = getAlertMock(false, getMlRuleParams()); alertServices.savedObjectsClient.get.mockResolvedValue({ id: 'id', type: 'type', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index dc929ed0fdeb1..aee265a2cfdfe 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -62,6 +62,12 @@ import { import { WrappedRACAlert } from '../rule_types/types'; import { SearchTypes } from '../../../../common/detection_engine/types'; import { IRuleExecutionLogClient } from '../rule_execution_log/types'; +import { + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, + QUERY_RULE_TYPE_ID, + SIGNALS_ID, +} from '../../../../common/constants'; interface SortExceptionsReturn { exceptionsWithValueLists: ExceptionListItemSchema[]; @@ -999,3 +1005,15 @@ export const getField = (event: SimpleHit, field: string) return get(event._source, field) as T; } }; + +/** + * Maps legacy rule types to RAC rule type IDs. + */ +export const ruleTypeMappings = { + eql: SIGNALS_ID, + machine_learning: ML_RULE_TYPE_ID, + query: QUERY_RULE_TYPE_ID, + saved_query: SIGNALS_ID, + threat_match: INDICATOR_RULE_TYPE_ID, + threshold: SIGNALS_ID, +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.test.ts index 1b7bf048646ed..505f8958ca44d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.test.ts @@ -11,19 +11,22 @@ import { INTERNAL_RULE_ID_KEY, INTERNAL_IDENTIFIER } from '../../../../common/co import { readRawTags, readTags, convertTagsToSet, convertToTags, isTags } from './read_tags'; import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; -describe('read_tags', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('read_tags - %s', (_, isRuleRegistryEnabled) => { afterEach(() => { jest.resetAllMocks(); }); describe('readRawTags', () => { test('it should return the intersection of tags to where none are repeating', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 2', 'tag 3']; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = ['tag 1', 'tag 2', 'tag 3', 'tag 4']; @@ -31,17 +34,17 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1, result2] })); - const tags = await readRawTags({ rulesClient }); + const tags = await readRawTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1', 'tag 2', 'tag 3', 'tag 4']); }); test('it should return the intersection of tags to where some are repeating values', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3']; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3', 'tag 4']; @@ -49,17 +52,17 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1, result2] })); - const tags = await readRawTags({ rulesClient }); + const tags = await readRawTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1', 'tag 2', 'tag 3', 'tag 4']); }); test('it should work with no tags defined between two results', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = []; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = []; @@ -67,12 +70,12 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1, result2] })); - const tags = await readRawTags({ rulesClient }); + const tags = await readRawTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual([]); }); test('it should work with a single tag which has repeating values in it', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 1', 'tag 1', 'tag 2']; @@ -80,12 +83,12 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1] })); - const tags = await readRawTags({ rulesClient }); + const tags = await readRawTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1', 'tag 2']); }); test('it should work with a single tag which has empty tags', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = []; @@ -93,19 +96,19 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1] })); - const tags = await readRawTags({ rulesClient }); + const tags = await readRawTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual([]); }); }); describe('readTags', () => { test('it should return the intersection of tags to where none are repeating', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 2', 'tag 3']; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = ['tag 1', 'tag 2', 'tag 3', 'tag 4']; @@ -113,17 +116,17 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1, result2] })); - const tags = await readTags({ rulesClient }); + const tags = await readTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1', 'tag 2', 'tag 3', 'tag 4']); }); test('it should return the intersection of tags to where some are repeating values', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3']; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3', 'tag 4']; @@ -131,17 +134,17 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1, result2] })); - const tags = await readTags({ rulesClient }); + const tags = await readTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1', 'tag 2', 'tag 3', 'tag 4']); }); test('it should work with no tags defined between two results', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = []; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = []; @@ -149,12 +152,12 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1, result2] })); - const tags = await readTags({ rulesClient }); + const tags = await readTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual([]); }); test('it should work with a single tag which has repeating values in it', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 1', 'tag 1', 'tag 2']; @@ -162,12 +165,12 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1] })); - const tags = await readTags({ rulesClient }); + const tags = await readTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1', 'tag 2']); }); test('it should work with a single tag which has empty tags', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = []; @@ -175,12 +178,12 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1] })); - const tags = await readTags({ rulesClient }); + const tags = await readTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual([]); }); test('it should filter out any __internal tags for things such as alert_id', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = [ @@ -192,12 +195,12 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1] })); - const tags = await readTags({ rulesClient }); + const tags = await readTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1']); }); test('it should filter out any __internal tags with two different results', async () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = [ @@ -210,7 +213,7 @@ describe('read_tags', () => { 'tag 5', ]; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = [ @@ -225,19 +228,19 @@ describe('read_tags', () => { const rulesClient = rulesClientMock.create(); rulesClient.find.mockResolvedValue(getFindResultWithMultiHits({ data: [result1] })); - const tags = await readTags({ rulesClient }); + const tags = await readTags({ isRuleRegistryEnabled, rulesClient }); expect(tags).toEqual(['tag 1', 'tag 2', 'tag 3', 'tag 4', 'tag 5']); }); }); describe('convertTagsToSet', () => { test('it should convert the intersection of two tag systems without duplicates', () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3']; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3', 'tag 4']; @@ -255,12 +258,12 @@ describe('read_tags', () => { describe('convertToTags', () => { test('it should convert the two tag systems together with duplicates', () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3']; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result2.params.ruleId = 'rule-2'; result2.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3', 'tag 4']; @@ -281,18 +284,18 @@ describe('read_tags', () => { }); test('it should filter out anything that is not a tag', () => { - const result1 = getAlertMock(getQueryRuleParams()); + const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result1.id = '4baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result1.params.ruleId = 'rule-1'; result1.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3']; - const result2 = getAlertMock(getQueryRuleParams()); + const result2 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result2.id = '99979e67-19a7-455f-b452-8eded6135716'; result2.params.ruleId = 'rule-2'; // @ts-expect-error delete result2.tags; - const result3 = getAlertMock(getQueryRuleParams()); + const result3 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); result3.id = '5baa53f8-96da-44ee-ad58-41bccb7f9f3d'; result3.params.ruleId = 'rule-2'; result3.tags = ['tag 1', 'tag 2', 'tag 2', 'tag 3', 'tag 4']; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.ts index 2314a8a49f567..183ac6f777963 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/tags/read_tags.ts @@ -40,22 +40,27 @@ export const convertTagsToSet = (tagObjects: object[]): Set => { // then this should be replaced with a an aggregation call. // Ref: https://www.elastic.co/guide/en/kibana/master/saved-objects-api.html export const readTags = async ({ + isRuleRegistryEnabled, rulesClient, }: { + isRuleRegistryEnabled: boolean; rulesClient: RulesClient; }): Promise => { - const tags = await readRawTags({ rulesClient }); + const tags = await readRawTags({ isRuleRegistryEnabled, rulesClient }); return tags.filter((tag) => !tag.startsWith(INTERNAL_IDENTIFIER)); }; export const readRawTags = async ({ + isRuleRegistryEnabled, rulesClient, }: { + isRuleRegistryEnabled: boolean; rulesClient: RulesClient; perPage?: number; }): Promise => { // Get just one record so we can get the total count const firstTags = await findRules({ + isRuleRegistryEnabled, rulesClient, fields: ['tags'], perPage: 1, @@ -66,6 +71,7 @@ export const readRawTags = async ({ }); // Get all the rules to aggregate over all the tags of the rules const rules = await findRules({ + isRuleRegistryEnabled, rulesClient, fields: ['tags'], perPage: firstTags.total, diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/helpers.test.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/helpers.test.ts index f30f80a4cf14c..c384c1df80ad1 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/helpers.test.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/helpers.test.ts @@ -5,8 +5,6 @@ * 2.0. */ -import { join, resolve } from 'path'; - import { createPromiseFromStreams } from '@kbn/utils'; import { SecurityPluginSetup } from '../../../../../../../security/server'; @@ -21,17 +19,20 @@ import { getFindResultWithSingleHit, } from '../../../../detection_engine/routes/__mocks__/request_responses'; -import * as lib from './helpers'; -import { importTimelines } from '../../timelines/import_timelines'; +import * as helpers from './helpers'; +import { importTimelines } from '../../timelines/import_timelines/helpers'; import { buildFrameworkRequest } from '../../../utils/common'; import { ImportTimelineResultSchema } from '../../../../../../common/types/timeline'; -jest.mock('../../timelines/import_timelines'); +jest.mock('../../timelines/import_timelines/helpers'); -describe('installPrepackagedTimelines', () => { +describe.each([ + ['Legacy', false], + ['RAC', true], +])('installPrepackagedTimelines - %s', (_, isRuleRegistryEnabled) => { let securitySetup: SecurityPluginSetup; let frameworkRequest: FrameworkRequest; - const spyInstallPrepackagedTimelines = jest.spyOn(lib, 'installPrepackagedTimelines'); + const spyInstallPrepackagedTimelines = jest.spyOn(helpers, 'installPrepackagedTimelines'); const { clients, context } = requestContextMock.createTools(); const config = createMockConfig(); @@ -46,11 +47,11 @@ describe('installPrepackagedTimelines', () => { authz: {}, } as unknown) as SecurityPluginSetup; - clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled)); jest.doMock('./helpers', () => { return { - ...lib, + ...helpers, installPrepackagedTimelines: spyInstallPrepackagedTimelines, }; }); @@ -60,7 +61,7 @@ describe('installPrepackagedTimelines', () => { }); afterEach(() => { - spyInstallPrepackagedTimelines.mockClear(); + jest.clearAllMocks(); }); afterAll(() => { @@ -68,10 +69,10 @@ describe('installPrepackagedTimelines', () => { }); test('should call importTimelines', async () => { - await lib.installPrepackagedTimelines( + await helpers.installPrepackagedTimelines( config.maxTimelineImportExportSize, frameworkRequest, - true, + false, mockFilePath, mockFileName ); @@ -80,14 +81,12 @@ describe('installPrepackagedTimelines', () => { }); test('should call importTimelines with Readables', async () => { - const dir = resolve(join(__dirname, mockFilePath)); - const file = mockFileName; - await lib.installPrepackagedTimelines( + await helpers.installPrepackagedTimelines( config.maxTimelineImportExportSize, frameworkRequest, true, - dir, - file + mockFilePath, + mockFileName ); const args = await createPromiseFromStreams([(importTimelines as jest.Mock).mock.calls[0][0]]); const expected = JSON.stringify({ @@ -194,14 +193,12 @@ describe('installPrepackagedTimelines', () => { }); test('should call importTimelines with maxTimelineImportExportSize', async () => { - const dir = resolve(join(__dirname, mockFilePath)); - const file = mockFileName; - await lib.installPrepackagedTimelines( + await helpers.installPrepackagedTimelines( config.maxTimelineImportExportSize, frameworkRequest, true, - dir, - file + mockFilePath, + mockFileName ); expect((importTimelines as jest.Mock).mock.calls[0][1]).toEqual( @@ -210,14 +207,12 @@ describe('installPrepackagedTimelines', () => { }); test('should call importTimelines with frameworkRequest', async () => { - const dir = resolve(join(__dirname, mockFilePath)); - const file = mockFileName; - await lib.installPrepackagedTimelines( + await helpers.installPrepackagedTimelines( config.maxTimelineImportExportSize, frameworkRequest, true, - dir, - file + mockFilePath, + mockFileName ); expect(JSON.stringify((importTimelines as jest.Mock).mock.calls[0][2])).toEqual( @@ -226,21 +221,19 @@ describe('installPrepackagedTimelines', () => { }); test('should call importTimelines with immutable', async () => { - const dir = resolve(join(__dirname, mockFilePath)); - const file = mockFileName; - await lib.installPrepackagedTimelines( + await helpers.installPrepackagedTimelines( config.maxTimelineImportExportSize, frameworkRequest, true, - dir, - file + mockFilePath, + mockFileName ); expect((importTimelines as jest.Mock).mock.calls[0][3]).toEqual(true); }); test('should handle errors from getReadables', async () => { - const result = await lib.installPrepackagedTimelines( + const result = await helpers.installPrepackagedTimelines( config.maxTimelineImportExportSize, frameworkRequest, true, diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 4e4d0be5a7411..e1af47de8f152 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -63,10 +63,10 @@ import { SERVER_APP_ID, SIGNALS_ID, NOTIFICATIONS_ID, - QUERY_ALERT_TYPE_ID, + QUERY_RULE_TYPE_ID, DEFAULT_SPACE_ID, - INDICATOR_ALERT_TYPE_ID, - ML_ALERT_TYPE_ID, + INDICATOR_RULE_TYPE_ID, + ML_RULE_TYPE_ID, } from '../common/constants'; import { registerEndpointRoutes } from './endpoint/routes/metadata'; import { registerLimitedConcurrencyRoutes } from './endpoint/routes/limited_concurrency'; @@ -272,7 +272,7 @@ export class Plugin implements IPlugin { // Detection Engine Rule routes that have the REST endpoints of /api/detection_engine/rules // All REST rule creation, deletion, updating, etc...... - createRulesRoute(router, ml, ruleDataClient); - readRulesRoute(router, ruleDataClient); - updateRulesRoute(router, ml, ruleDataClient); - patchRulesRoute(router, ml, ruleDataClient); - deleteRulesRoute(router, ruleDataClient); - findRulesRoute(router, ruleDataClient); - - // TODO: pass ruleDataClient to all relevant routes - - addPrepackedRulesRoute(router, config, security); - getPrepackagedRulesStatusRoute(router, config, security); - createRulesBulkRoute(router, ml); - updateRulesBulkRoute(router, ml); - patchRulesBulkRoute(router, ml); - deleteRulesBulkRoute(router); - performBulkActionRoute(router, ml); + createRulesRoute(router, ml, isRuleRegistryEnabled); + readRulesRoute(router, isRuleRegistryEnabled); + updateRulesRoute(router, ml, isRuleRegistryEnabled); + patchRulesRoute(router, ml, isRuleRegistryEnabled); + deleteRulesRoute(router, isRuleRegistryEnabled); + findRulesRoute(router, isRuleRegistryEnabled); + + // TODO: pass isRuleRegistryEnabled to all relevant routes + + addPrepackedRulesRoute(router, config, security, isRuleRegistryEnabled); + getPrepackagedRulesStatusRoute(router, config, security, isRuleRegistryEnabled); + createRulesBulkRoute(router, ml, isRuleRegistryEnabled); + updateRulesBulkRoute(router, ml, isRuleRegistryEnabled); + patchRulesBulkRoute(router, ml, isRuleRegistryEnabled); + deleteRulesBulkRoute(router, isRuleRegistryEnabled); + performBulkActionRoute(router, ml, isRuleRegistryEnabled); createTimelinesRoute(router, config, security); patchTimelinesRoute(router, config, security); - importRulesRoute(router, config, ml); - exportRulesRoute(router, config); + importRulesRoute(router, config, ml, isRuleRegistryEnabled); + exportRulesRoute(router, config, isRuleRegistryEnabled); importTimelinesRoute(router, config, security); exportTimelinesRoute(router, config, security); @@ -123,7 +123,7 @@ export const initRoutes = ( deleteIndexRoute(router); // Detection Engine tags routes that have the REST endpoints of /api/detection_engine/tags - readTagsRoute(router); + readTagsRoute(router, isRuleRegistryEnabled); // Privileges API to get the generic user privileges readPrivilegesRoute(router, hasEncryptionKey); From de2cfd2e65ff9d3cdda0df5fd25c32f86a3e6dd0 Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 9 Sep 2021 11:26:08 -0700 Subject: [PATCH 18/32] [ci] bump Jenkins worker memory and es JVM size (#111760) Co-authored-by: spalger --- packages/kbn-es/src/cluster.js | 3 ++- packages/kbn-es/src/integration_tests/cluster.test.js | 4 ++-- vars/workers.groovy | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index 32709fc608617..ac4380da88be0 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -278,7 +278,8 @@ exports.Cluster = class Cluster { // especially because we currently run many instances of ES on the same machine during CI // inital and max must be the same, so we only need to check the max if (!esJavaOpts.includes('Xmx')) { - esJavaOpts += ' -Xms1g -Xmx1g'; + // 1536m === 1.5g + esJavaOpts += ' -Xms1536m -Xmx1536m'; } this._log.debug('ES_JAVA_OPTS: %s', esJavaOpts.trim()); diff --git a/packages/kbn-es/src/integration_tests/cluster.test.js b/packages/kbn-es/src/integration_tests/cluster.test.js index 34220b08d2120..c196a89a6b090 100644 --- a/packages/kbn-es/src/integration_tests/cluster.test.js +++ b/packages/kbn-es/src/integration_tests/cluster.test.js @@ -368,7 +368,7 @@ describe('#run()', () => { const cluster = new Cluster({ log }); await cluster.run(); - expect(execa.mock.calls[0][2].env.ES_JAVA_OPTS).toEqual('-Xms1g -Xmx1g'); + expect(execa.mock.calls[0][2].env.ES_JAVA_OPTS).toMatchInlineSnapshot(`"-Xms1536m -Xmx1536m"`); }); it('allows Java heap to be overwritten', async () => { @@ -378,7 +378,7 @@ describe('#run()', () => { const cluster = new Cluster({ log }); await cluster.run(); - expect(execa.mock.calls[0][2].env.ES_JAVA_OPTS).toEqual('-Xms5g -Xmx5g'); + expect(execa.mock.calls[0][2].env.ES_JAVA_OPTS).toMatchInlineSnapshot(`"-Xms5g -Xmx5g"`); }); }); diff --git a/vars/workers.groovy b/vars/workers.groovy index ca1c6b57c18bb..d95c3fdbb1b44 100644 --- a/vars/workers.groovy +++ b/vars/workers.groovy @@ -20,7 +20,7 @@ def label(size) { case 'xl-highmem': return 'docker && tests-xl-highmem' case 'xxl': - return 'docker && tests-xxl && gobld/machineType:custom-64-270336' + return 'docker && tests-xxl && gobld/machineType:custom-64-327680' case 'n2-standard-16': return 'docker && linux && immutable && gobld/machineType:n2-standard-16' } From 4d933c7d988086d3dff04e1484c89ab5908efbf0 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Thu, 9 Sep 2021 11:27:29 -0700 Subject: [PATCH 19/32] Replace hard-coded links in infra alerting (#111072) --- .../public/kibana-plugin-core-public.doclinksstart.links.md | 3 +++ .../core/public/kibana-plugin-core-public.doclinksstart.md | 2 +- src/core/public/doc_links/doc_links_service.ts | 6 ++++++ src/core/public/public.api.md | 3 +++ x-pack/plugins/infra/public/alerting/inventory/index.ts | 2 +- .../alerting/log_threshold/log_threshold_alert_type.ts | 2 +- .../plugins/infra/public/alerting/metric_threshold/index.ts | 2 +- 7 files changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 7e4ed7ec2dd1b..f40f52db55de9 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -190,6 +190,9 @@ readonly links: { }>; readonly observability: Readonly<{ guide: string; + infrastructureThreshold: string; + logsThreshold: string; + metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index 89156501d476e..2499227d20ad4 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly settings: string;
readonly apm: {
readonly kibanaSettings: string;
readonly supportedServiceMaps: string;
readonly customLinks: string;
readonly droppedTransactionSpans: string;
readonly upgrading: string;
readonly metaData: string;
};
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
readonly suricataModule: string;
readonly zeekModule: string;
};
readonly auditbeat: {
readonly base: string;
readonly auditdModule: string;
readonly systemModule: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly libbeat: {
readonly getStarted: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
readonly ruleChangeLog: string;
readonly detectionsReq: string;
readonly networkMap: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
readonly autocompleteChanges: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Readonly<{
guide: string;
monitorStatus: string;
monitorUptime: string;
tlsCertificate: string;
uptimeDurationAnomaly: string;
}>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
}>;
readonly ecs: {
readonly guide: string;
};
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly settings: string;
readonly apm: {
readonly kibanaSettings: string;
readonly supportedServiceMaps: string;
readonly customLinks: string;
readonly droppedTransactionSpans: string;
readonly upgrading: string;
readonly metaData: string;
};
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
readonly suricataModule: string;
readonly zeekModule: string;
};
readonly auditbeat: {
readonly base: string;
readonly auditdModule: string;
readonly systemModule: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly libbeat: {
readonly getStarted: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
readonly ruleChangeLog: string;
readonly detectionsReq: string;
readonly networkMap: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
readonly autocompleteChanges: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Readonly<{
guide: string;
infrastructureThreshold: string;
logsThreshold: string;
metricsThreshold: string;
monitorStatus: string;
monitorUptime: string;
tlsCertificate: string;
uptimeDurationAnomaly: string;
}>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
}>;
readonly ecs: {
readonly guide: string;
};
} | | diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index ca174fc12109d..958cae8816efa 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -282,6 +282,9 @@ export class DocLinksService { }, observability: { guide: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/index.html`, + infrastructureThreshold: `{ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/infrastructure-threshold-alert.html`, + logsThreshold: `{ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/logs-threshold-alert.html`, + metricsThreshold: `{ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/metrics-threshold-alert.html`, monitorStatus: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/monitor-status-alert.html`, monitorUptime: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/monitor-uptime.html`, tlsCertificate: `${ELASTIC_WEBSITE_URL}guide/en/observability/${DOC_LINK_VERSION}/tls-certificate-alert.html`, @@ -645,6 +648,9 @@ export interface DocLinksStart { }>; readonly observability: Readonly<{ guide: string; + infrastructureThreshold: string; + logsThreshold: string; + metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 0135526bb6385..8d3291d590476 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -655,6 +655,9 @@ export interface DocLinksStart { }>; readonly observability: Readonly<{ guide: string; + infrastructureThreshold: string; + logsThreshold: string; + metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; diff --git a/x-pack/plugins/infra/public/alerting/inventory/index.ts b/x-pack/plugins/infra/public/alerting/inventory/index.ts index 7d370c7106cb7..5e3c8a219ae47 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/index.ts +++ b/x-pack/plugins/infra/public/alerting/inventory/index.ts @@ -31,7 +31,7 @@ export function createInventoryMetricAlertType(): ObservabilityRuleTypeModel import('./components/expression')), validate: validateMetricThreshold, diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_alert_type.ts b/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_alert_type.ts index b944b36fb9d1a..c6b2385f93c65 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_alert_type.ts +++ b/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_alert_type.ts @@ -23,7 +23,7 @@ export function createLogThresholdAlertType(): ObservabilityRuleTypeModel import('./components/expression_editor/editor')), validate: validateExpression, diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts b/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts index 2dd35c20a5632..679019eb2e520 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts @@ -29,7 +29,7 @@ export function createMetricThresholdAlertType(): ObservabilityRuleTypeModel import('./components/expression')), validate: validateMetricThreshold, From 4b60458c4ba3de4716a8da4e9862c0f5effc26c1 Mon Sep 17 00:00:00 2001 From: Nick Peihl Date: Thu, 9 Sep 2021 11:37:57 -0700 Subject: [PATCH 20/32] [Maps] Remove deprecated maps.manifestServiceUrl configuration (#111656) * Remove deprecated maps.manifestServiceUrl * Remove unused catalogue route * Remove unused import Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../config/deprecation/core_deprecations.ts | 24 ----------- src/plugins/maps_ems/config.ts | 1 - src/plugins/maps_ems/server/index.ts | 1 - x-pack/plugins/maps/common/constants.ts | 1 - x-pack/plugins/maps/server/routes.js | 41 ------------------- 5 files changed, 68 deletions(-) diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 222f92321d917..2ddcbc8db774d 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -124,28 +124,6 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecati } }; -const mapManifestServiceUrlDeprecation: ConfigDeprecation = ( - settings, - fromPath, - addDeprecation -) => { - if (settings.map?.manifestServiceUrl) { - addDeprecation({ - message: - 'You should no longer use the map.manifestServiceUrl setting in kibana.yml to configure the location ' + - 'of the Elastic Maps Service settings. These settings have moved to the "map.emsTileApiUrl" and ' + - '"map.emsFileApiUrl" settings instead. These settings are for development use only and should not be ' + - 'modified for use in production environments.', - correctiveActions: { - manualSteps: [ - `Use "map.emsTileApiUrl" and "map.emsFileApiUrl" config instead of "map.manifestServiceUrl".`, - `These settings are for development use only and should not be modified for use in production environments.`, - ], - }, - }); - } -}; - const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (settings.logging?.events?.ops) { addDeprecation({ @@ -388,7 +366,6 @@ const logFilterDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecat export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unusedFromRoot }) => [ unusedFromRoot('savedObjects.indexCheckTimeout'), unusedFromRoot('server.xsrf.token'), - unusedFromRoot('maps.manifestServiceUrl'), unusedFromRoot('optimize.lazy'), unusedFromRoot('optimize.lazyPort'), unusedFromRoot('optimize.lazyHost'), @@ -418,7 +395,6 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unu dataPathDeprecation, rewriteBasePathDeprecation, cspRulesDeprecation, - mapManifestServiceUrlDeprecation, opsLoggingEventDeprecation, requestLoggingEventDeprecation, timezoneLoggingDeprecation, diff --git a/src/plugins/maps_ems/config.ts b/src/plugins/maps_ems/config.ts index ed1648ebbe8bb..710cb52f32a09 100644 --- a/src/plugins/maps_ems/config.ts +++ b/src/plugins/maps_ems/config.ts @@ -40,7 +40,6 @@ export const emsConfigSchema = schema.object({ tilemap: tilemapConfigSchema, includeElasticMapsService: schema.boolean({ defaultValue: true }), proxyElasticMapsServiceInMaps: schema.boolean({ defaultValue: false }), - manifestServiceUrl: schema.string({ defaultValue: '' }), emsUrl: schema.conditional( schema.siblingRef('proxyElasticMapsServiceInMaps'), true, diff --git a/src/plugins/maps_ems/server/index.ts b/src/plugins/maps_ems/server/index.ts index b8b84d222b958..7422dbcfcdec9 100644 --- a/src/plugins/maps_ems/server/index.ts +++ b/src/plugins/maps_ems/server/index.ts @@ -19,7 +19,6 @@ export const config: PluginConfigDescriptor = { tilemap: true, includeElasticMapsService: true, proxyElasticMapsServiceInMaps: true, - manifestServiceUrl: true, emsUrl: true, emsFileApiUrl: true, emsTileApiUrl: true, diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 5cfed7d6a58b5..b6b3e636fffeb 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n'; import { FeatureCollection } from 'geojson'; export const EMS_APP_NAME = 'kibana'; -export const EMS_CATALOGUE_PATH = 'ems/catalogue'; export const EMS_FILES_CATALOGUE_PATH = 'ems/files'; export const EMS_FILES_API_PATH = 'ems/files'; diff --git a/x-pack/plugins/maps/server/routes.js b/x-pack/plugins/maps/server/routes.js index 635770a562c2d..bff2f1ee24c9f 100644 --- a/x-pack/plugins/maps/server/routes.js +++ b/x-pack/plugins/maps/server/routes.js @@ -7,7 +7,6 @@ import { EMS_APP_NAME, - EMS_CATALOGUE_PATH, EMS_FILES_API_PATH, EMS_FILES_CATALOGUE_PATH, EMS_FILES_DEFAULT_JSON_PATH, @@ -19,7 +18,6 @@ import { EMS_TILES_VECTOR_STYLE_PATH, EMS_TILES_VECTOR_SOURCE_PATH, EMS_TILES_VECTOR_TILE_PATH, - GIS_API_PATH, EMS_SPRITES_PATH, INDEX_SETTINGS_API_PATH, FONTS_API_PATH, @@ -42,9 +40,6 @@ const EMPTY_EMS_CLIENT = { async getTMSServices() { return []; }, - async getMainManifest() { - return null; - }, async getDefaultFileManifest() { return null; }, @@ -163,42 +158,6 @@ export async function initRoutes(core, getLicenseId, emsSettings, kbnVersion, lo } ); - router.get( - { - path: `${API_ROOT_PATH}/${EMS_CATALOGUE_PATH}`, - validate: false, - }, - async (context, request, { ok, badRequest }) => { - if (!checkEMSProxyEnabled()) { - return badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - const main = await getEMSClient().getMainManifest(); - const proxiedManifest = { - services: [], - }; - - //rewrite the urls to the submanifest - const tileService = main.services.find((service) => service.type === 'tms'); - const fileService = main.services.find((service) => service.type === 'file'); - if (tileService) { - proxiedManifest.services.push({ - ...tileService, - manifest: `${GIS_API_PATH}/${EMS_TILES_CATALOGUE_PATH}`, - }); - } - if (fileService) { - proxiedManifest.services.push({ - ...fileService, - manifest: `${GIS_API_PATH}/${EMS_FILES_CATALOGUE_PATH}`, - }); - } - return ok({ - body: proxiedManifest, - }); - } - ); - router.get( { path: `${API_ROOT_PATH}/${EMS_FILES_CATALOGUE_PATH}/{emsVersion}/manifest`, From 7ee68bea8e5f212f66261e2609b2d94b24002937 Mon Sep 17 00:00:00 2001 From: Domenico Andreoli Date: Thu, 9 Sep 2021 20:41:59 +0200 Subject: [PATCH 21/32] Drop the 'Displays the unmapped field on the table' test (#111741) It's too unstable for now --- .../detection_alerts/alerts_details.spec.ts | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts index 3263eb9d70b66..825abc6185947 100644 --- a/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts +++ b/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { ALERT_FLYOUT, CELL_TEXT, JSON_LINES, TABLE_ROWS } from '../../screens/alerts_details'; +import { ALERT_FLYOUT, JSON_LINES } from '../../screens/alerts_details'; import { expandFirstAlert, waitForAlertsIndexToBeCreated, waitForAlertsPanelToBeLoaded, } from '../../tasks/alerts'; -import { openJsonView, openTable, scrollJsonViewToBottom } from '../../tasks/alerts_details'; +import { openJsonView, scrollJsonViewToBottom } from '../../tasks/alerts_details'; import { createCustomRuleActivated } from '../../tasks/api_calls/rules'; import { cleanKibana } from '../../tasks/common'; import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login'; @@ -55,21 +55,4 @@ describe('Alert details with unmapped fields', () => { .should('include', expectedUnmappedField.text); }); }); - - it('Displays the unmapped field on the table', () => { - const expectedUnmmappedField = { - row: 90, - field: 'unmapped', - text: 'This is the unmapped field', - }; - - openTable(); - cy.get(ALERT_FLYOUT) - .find(TABLE_ROWS) - .eq(expectedUnmmappedField.row) - .within(() => { - cy.get(CELL_TEXT).eq(2).should('have.text', expectedUnmmappedField.field); - cy.get(CELL_TEXT).eq(4).should('have.text', expectedUnmmappedField.text); - }); - }); }); From 3f83259db7ee8ec8069a034f7508859f4e30d08a Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 9 Sep 2021 14:22:48 -0500 Subject: [PATCH 22/32] [config] Deprecate `KIBANA_PATH_CONF` in favor of `KBN_PATH_CONF` (#111550) --- packages/kbn-utils/src/path/index.ts | 4 ++-- .../deprecation/core_deprecations.test.ts | 18 ++++++++++++++++++ .../config/deprecation/core_deprecations.ts | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/kbn-utils/src/path/index.ts b/packages/kbn-utils/src/path/index.ts index 9835179a61e9d..9d371a0c334a9 100644 --- a/packages/kbn-utils/src/path/index.ts +++ b/packages/kbn-utils/src/path/index.ts @@ -15,7 +15,7 @@ const isString = (v: any): v is string => typeof v === 'string'; const CONFIG_PATHS = [ process.env.KBN_PATH_CONF && join(process.env.KBN_PATH_CONF, 'kibana.yml'), - process.env.KIBANA_PATH_CONF && join(process.env.KIBANA_PATH_CONF, 'kibana.yml'), + process.env.KIBANA_PATH_CONF && join(process.env.KIBANA_PATH_CONF, 'kibana.yml'), // deprecated process.env.CONFIG_PATH, // deprecated join(REPO_ROOT, 'config/kibana.yml'), '/etc/kibana/kibana.yml', @@ -23,7 +23,7 @@ const CONFIG_PATHS = [ const CONFIG_DIRECTORIES = [ process.env.KBN_PATH_CONF, - process.env.KIBANA_PATH_CONF, + process.env.KIBANA_PATH_CONF, // deprecated join(REPO_ROOT, 'config'), '/etc/kibana', ].filter(isString); diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index 759e2375ce987..a3bc9ee669903 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -36,6 +36,24 @@ describe('core deprecations', () => { }); }); + describe('kibanaPathConf', () => { + it('logs a warning if KIBANA_PATH_CONF environ variable is set', () => { + process.env.KIBANA_PATH_CONF = 'somepath'; + const { messages } = applyCoreDeprecations(); + expect(messages).toMatchInlineSnapshot(` + Array [ + "Environment variable \\"KIBANA_PATH_CONF\\" is deprecated. It has been replaced with \\"KBN_PATH_CONF\\" pointing to a config folder", + ] + `); + }); + + it('does not log a warning if KIBANA_PATH_CONF environ variable is unset', () => { + delete process.env.KIBANA_PATH_CONF; + const { messages } = applyCoreDeprecations(); + expect(messages).toHaveLength(0); + }); + }); + describe('dataPath', () => { it('logs a warning if DATA_PATH environ variable is set', () => { process.env.DATA_PATH = 'somepath'; diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 2ddcbc8db774d..70c987e156448 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -8,6 +8,19 @@ import { ConfigDeprecationProvider, ConfigDeprecation } from '@kbn/config'; +const kibanaPathConf: ConfigDeprecation = (settings, fromPath, addDeprecation) => { + if (process.env?.KIBANA_PATH_CONF) { + addDeprecation({ + message: `Environment variable "KIBANA_PATH_CONF" is deprecated. It has been replaced with "KBN_PATH_CONF" pointing to a config folder`, + correctiveActions: { + manualSteps: [ + 'Use "KBN_PATH_CONF" instead of "KIBANA_PATH_CONF" to point to a config folder.', + ], + }, + }); + } +}; + const configPathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (process.env?.CONFIG_PATH) { addDeprecation({ @@ -392,6 +405,7 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unu rename('server.xsrf.whitelist', 'server.xsrf.allowlist'), rewriteCorsSettings, configPathDeprecation, + kibanaPathConf, dataPathDeprecation, rewriteBasePathDeprecation, cspRulesDeprecation, From 914fa092c071318aecf0c9ffa99db7605526666e Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 9 Sep 2021 14:46:11 -0500 Subject: [PATCH 23/32] Bump tar to 6.1.11 (#111602) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 4 +-- yarn.lock | 73 +++++++--------------------------------------------- 2 files changed, 11 insertions(+), 66 deletions(-) diff --git a/package.json b/package.json index e8ac3a65924b2..0dee7a131f98a 100644 --- a/package.json +++ b/package.json @@ -387,7 +387,7 @@ "suricata-sid-db": "^1.0.2", "symbol-observable": "^1.2.0", "tabbable": "1.1.3", - "tar": "4.4.13", + "tar": "^6.1.11", "tinycolor2": "1.4.1", "tinygradient": "0.4.3", "tree-kill": "^1.2.2", @@ -619,7 +619,7 @@ "@types/styled-components": "^5.1.0", "@types/supertest": "^2.0.5", "@types/tapable": "^1.0.6", - "@types/tar": "^4.0.3", + "@types/tar": "^4.0.5", "@types/tar-fs": "^1.16.1", "@types/tempy": "^0.2.0", "@types/testing-library__jest-dom": "^5.9.5", diff --git a/yarn.lock b/yarn.lock index 1c91896c1f063..6b242fa46b2bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6164,10 +6164,10 @@ dependencies: "@types/node" "*" -"@types/tar@^4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/tar/-/tar-4.0.3.tgz#e2cce0b8ff4f285293243f5971bd7199176ac489" - integrity sha512-Z7AVMMlkI8NTWF0qGhC4QIX0zkV/+y0J8x7b/RsHrN0310+YNjoJd8UrApCiGBCWtKjxS9QhNqLi2UJNToh5hA== +"@types/tar@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tar/-/tar-4.0.5.tgz#5f953f183e36a15c6ce3f336568f6051b7b183f3" + integrity sha512-cgwPhNEabHaZcYIy5xeMtux2EmYBitfqEceBUi2t5+ETy4dW6kswt6WX4+HqLeiiKOo42EXbGiDmVJ2x+vi37Q== dependencies: "@types/minipass" "*" "@types/node" "*" @@ -14238,13 +14238,6 @@ fs-extra@^9.0.0, fs-extra@^9.0.1: jsonfile "^6.0.1" universalify "^1.0.0" -fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== - dependencies: - minipass "^2.2.1" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -19517,14 +19510,6 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^2.2.1, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - minipass@^3.0.0, minipass@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" @@ -19539,13 +19524,6 @@ minipass@^3.1.0, minipass@^3.1.3: dependencies: yallist "^4.0.0" -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - minizlib@^2.0.0, minizlib@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" @@ -19554,14 +19532,6 @@ minizlib@^2.0.0, minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -minizlib@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" - integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -26586,19 +26556,6 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar@4.4.13: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - tar@6.1.9: version "6.1.9" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.9.tgz#5646ef51342ac55456b2466e44da810439978db1" @@ -26611,22 +26568,10 @@ tar@6.1.9: mkdirp "^1.0.3" yallist "^4.0.0" -tar@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" - integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.0" - mkdirp "^1.0.3" - yallist "^4.0.0" - -tar@^6.1.2: - version "6.1.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.10.tgz#8a320a74475fba54398fa136cd9883aa8ad11175" - integrity sha512-kvvfiVvjGMxeUNB6MyYv5z7vhfFRwbwCXJAeL0/lnbrttBVqcMOnpHUf0X42LrPMR8mMpgapkJMchFH4FSHzNA== +tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" @@ -29497,7 +29442,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== From 6803fb362a3e1ccfe7cccb84998011eda1b17e38 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 9 Sep 2021 14:54:30 -0500 Subject: [PATCH 24/32] Upgrade EUI to v37.6.0 (#110998) * eui to 37.6.0 * update snapshots * grid cell text * update snapshot * Revert "grid cell text" This reverts commit 1721e8393959524abaaba85e9cf4ca7862d14a4a. * grid cell text * update tsvb baseline * update area_chart baseline Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 2 +- src/dev/license_checker/config.ts | 2 +- .../__snapshots__/table_cell.test.tsx.snap | 4 +- .../__snapshots__/source_viewer.test.tsx.snap | 2 +- .../recently_accessed.test.js.snap | 2 + .../vis/__snapshots__/form_row.test.tsx.snap | 2 + .../__snapshots__/code_editor.test.tsx.snap | 1 - .../__snapshots__/relationships.test.tsx.snap | 6 +++ .../__snapshots__/agg.test.tsx.snap | 1 + .../value_axes_panel.test.tsx.snap | 5 ++ .../screenshots/baseline/area_chart.png | Bin 85012 -> 67063 bytes .../screenshots/baseline/tsvb_dashboard.png | Bin 73146 -> 122776 bytes .../List/__snapshots__/List.test.tsx.snap | 18 ------- .../shared/TimestampTooltip/index.test.tsx | 1 + .../sticky_properties.test.tsx.snap | 5 ++ .../__snapshots__/asset.stories.storyshot | 8 --- .../asset_manager.stories.storyshot | 8 --- .../expression_input.stories.storyshot | 1 - .../workpad_table.stories.storyshot | 6 --- .../element_controls.stories.storyshot | 2 - .../element_grid.stories.storyshot | 6 --- .../saved_elements_modal.stories.storyshot | 8 --- .../sidebar_header.stories.storyshot | 4 -- .../var_config.stories.storyshot | 2 - .../simple_template.stories.storyshot | 1 - .../field_type_icon.test.tsx.snap | 1 + .../__snapshots__/scaling_form.test.tsx.snap | 3 ++ ...single_layer_source_settings.test.tsx.snap | 4 ++ .../dynamic_color_property.test.tsx.snap | 5 ++ .../dynamic_icon_property.test.tsx.snap | 1 + .../__snapshots__/join_editor.test.tsx.snap | 2 + .../__snapshots__/layer_control.test.tsx.snap | 7 +++ .../__snapshots__/list.test.tsx.snap | 6 +++ ...get_alert_panels_by_category.test.tsx.snap | 8 +++ .../get_alert_panels_by_node.test.tsx.snap | 8 +++ .../__snapshots__/tooltip.test.js.snap | 25 ++++++++++ .../shared/timestamp_tooltip/index.test.tsx | 1 + .../report_listing.test.tsx.snap | 32 ++++++------ ...screen_capture_panel_content.test.tsx.snap | 6 +-- .../__snapshots__/index.test.tsx.snap | 2 + .../__snapshots__/helpers.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 4 ++ .../__snapshots__/index.test.tsx.snap | 2 + .../sort_indicator.test.tsx.snap | 1 + .../sort_indicator.test.tsx.snap | 1 + .../start_action_name.test.tsx.snap | 1 + .../stop_action_name.test.tsx.snap | 1 + .../create_transform_button.test.tsx.snap | 1 + .../__snapshots__/donut_chart.test.tsx.snap | 46 ++++++++++++++++-- .../integration_link.test.tsx.snap | 2 + .../functional/services/transform/wizard.ts | 1 - yarn.lock | 8 +-- 52 files changed, 178 insertions(+), 99 deletions(-) diff --git a/package.json b/package.json index 0dee7a131f98a..5024d51852d2a 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.19", "@elastic/ems-client": "7.15.0", - "@elastic/eui": "37.3.1", + "@elastic/eui": "37.6.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "^9.0.1-kibana3", "@elastic/maki": "6.3.0", diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index ee355d6a9811b..addedbb97f55a 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -75,7 +75,7 @@ export const LICENSE_OVERRIDES = { '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint 'node-sql-parser@3.6.1': ['(GPL-2.0 OR MIT)'], // GPL-2.0* https://github.com/taozhi8833998/node-sql-parser '@elastic/ems-client@7.15.0': ['Elastic License 2.0'], - '@elastic/eui@37.3.1': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@37.6.0': ['SSPL-1.0 OR Elastic License 2.0'], // TODO can be removed if the https://github.com/jindw/xmldom/issues/239 is released 'xmldom@0.1.27': ['MIT'], diff --git a/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_row/__snapshots__/table_cell.test.tsx.snap b/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_row/__snapshots__/table_cell.test.tsx.snap index 5f3564174adf8..7f7a63bf139b0 100644 --- a/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_row/__snapshots__/table_cell.test.tsx.snap +++ b/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_row/__snapshots__/table_cell.test.tsx.snap @@ -31,11 +31,11 @@ exports[`Doc table cell component renders a cell with filter buttons if it is fi className="kbnDocTableCell__filterButton" content="Filter for value" delay="regular" + display="inlineBlock" position="bottom" > @@ -65,11 +65,11 @@ exports[`Doc table cell component renders a cell with filter buttons if it is fi className="kbnDocTableCell__filterButton" content="Filter out value" delay="regular" + display="inlineBlock" position="bottom" > diff --git a/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap b/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap index dfded530c6983..3d4a9923fa8c8 100644 --- a/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap +++ b/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap @@ -472,12 +472,12 @@ exports[`Source Viewer component renders json code editor 1`] = ` > diff --git a/src/plugins/home/public/application/components/__snapshots__/recently_accessed.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/recently_accessed.test.js.snap index c9fd411ab6070..09ca9c0c16f8a 100644 --- a/src/plugins/home/public/application/components/__snapshots__/recently_accessed.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/recently_accessed.test.js.snap @@ -45,6 +45,7 @@ exports[`render 1`] = ` anchorClassName="homRecentlyAccessed__anchor" content="label0" delay="regular" + display="inlineBlock" position="bottom" >

diff --git a/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap b/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap index 7b2729d2e1b68..d85f96382e803 100644 --- a/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap +++ b/src/plugins/kibana_react/public/code_editor/__snapshots__/code_editor.test.tsx.snap @@ -164,7 +164,6 @@ exports[` is rendered 1`] = ` > diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap index c39263f304249..6c07cb0c46ec6 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap @@ -14,6 +14,7 @@ exports[`Relationships should render dashboards normally 1`] = ` @@ -70,6 +72,7 @@ exports[`ValueAxesPanel component should init with the default set of props 1`] @@ -178,6 +182,7 @@ exports[`ValueAxesPanel component should init with the default set of props 1`] I_d!~6ce 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

vx;Fa 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 literal 85012 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 z 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

QA> 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 diff --git a/test/functional/screenshots/baseline/tsvb_dashboard.png b/test/functional/screenshots/baseline/tsvb_dashboard.png index a36cfffebf080fa86cf10cbc3f132e512eab92df..4b41887e27e246c30e547be4f734d7aad15fc4f1 100644 GIT binary patch literal 122776 zcmd43XH=72(*_!Bhy_#>1q2>7pme25$ASd=DxJ_n z2Wbg}B(x9+1kOg^@AY}lkMsMuR@RCsclMq=bImo^%+1>e8pIK8RD@=ksK z#g*b;)HkFP^jBjLn`X&2;m`cvJKt6~OHpr_p?^L3BiI8!@|LJRM%E~NC%(mIS<;_a z?lPR!#(jP$14=*J`Z>Egw^C3uG8S<)QwwoMsdTaIqH3$H(2v~@F{e@1l!G3=L0_k& zdc%E}<6jKts;Dh}xqXo;+`ut($9BXIVf>0@X}V3vqVTwc-~GpZW&6y=_y>jLT>a21 zvKJ-p+UiAJUOS#bxnF0mcz+TC`3C~KdrQ|Vd1>6!D_U>j=ZdeY6^~`_i$hSc1@%+9 zik}4^c^1FnIKEN3QQ>KT*&P`*()S#%z#HLSs?aY8mVfv#F`Cu2-E8st1aDS{g?2+4 zepN(sE5$YS#PtupT~bGK`xefEGy1=O#nA~d9JotjZI7e_yS=shodjZtmP6+~3y%OFDV;>obxe9DiSfSpEB3 z|K!)!CjQUcxqYxe#=jpAgdTAF`#;G4>wo{Vf`8sZP^QnNQ>eskF1JyF=VBqUQP0v+ zFFoYY-z%h~4xbP6+iA@;s&>&rVO|Q{QpJrM`)_abe2(HN&`djI?zZ5`F6q=8DvVl` zlHZzTc5nT0z5+HG%CeWk?o_XbSpN}c&VO?#M@KVZkjGyV{6e;ssi#h;ou-U?Vwb|6 z30K5X?eWP_Cb>-mG9Dutc;&DCr5V!>;fyPt287G7Vha54_iSEtw#sh%6|uTeT1P^x`1>rk7YqrB$a<@xz)nS6Ro!vuTIg zckQaO8Fx`$odX6`M_B@4_`k;(IJgQ6oVY05xC-YJ5*o~mkR2K{^}K*h@eBtW6D6pt zYWw*mTXn>9;x4&+DeQ?TBO6y@v0h&ScjXy;X#-Bm-7#r@k1i$3{J^@cPOc4jpO2rv zZ~BK?xqmYw5>INNyy%i%a|`2;`N;(we!R}T&p8xpKUzs(6SGOb&!dwbq8l>oFj!=0 z&~8Xrm);{wPJ%0py86v08R@qSo@KF-qe}sXqxnb zW}mLE?vhlM&5ASm2=47$nF=S`k?fqDd~389hm^>KC5oH)V*e6FNnONEG9kS-`Z+aYLS1DG34F}u96#1?@4YMaxjL(3K$lE zxAu33>&X`x*>Q#S@Cpr~1qHFKH@s>F}cAT?Buh78$$GaG|>yH986bNUL+a838 z%*S^^ysS2;(+P!zg%#dwEP|$$CZ|vTVw3YJKf=V8$MN>*Nh(uI%`DoX_a> zg!?|TAL$p9HPzMnm=tz!QVlDw@nVaoCimv+=bf^%vyDDKkJ%t;>RDOEK6(1IztBLF zLp&h)Wl)eDg)o^`PysJ0T)Pw=!*5VnUw?bN_Qzu0%8V?wudi>;C7PpjZ@!Wr#+r~| zRON)y*4`-0%X_%;Os+pylPiqF_tpD*nb?N3fL*153i z=2@N--jl9Q?SqbHl(Q@>i$9Z``gRT<$M-k?{D~u>~8Ozj~H!k;5)GHy4j+x3X)GEjGhy-V7+s(Nx&`fF=_>C-JGi zBxGOOY+~@<$R29;T$ZreP7<+h?-F{29od*6Iq74-F5wUjRZn(#56&oBnj*LLJu?-8 zszBGfEr^)HX9Ug4zH=LNJ64U7mt4`lU8t>}h0^#AQN}HQoBY`NdBplJXV^MrLC+Oy zO7Wr9(l(nY_>*9`zh^*F+&Hv4Y0puJaYt>Bha)#Lp!APJfU8 zx}}>_Zd%Xg-T6J*vQp9n{F8*COigL2Di?fJ6X_boqrU9t-`81%VbB(?o|5J8@ApEw z?wiXUFWEn;Y-g8v^*!V9D8js>SY<7(3UMef6*l!IHza9we@H3=9k;K3kb{|JDzS;_->? z-QQ2`yqgcnnW!e{-3idgseVfziN~gShNt>&*mhRqZX?&wG}>X1fo;G1Iw&@iaa`PH zN)d?%OYeUlD%20VntBa(>{#hF35lQh)SqTiIhA#fo9>}j=10vaW6#%4`php}6$7zt zhMf$+%E5Yh`*M6z_O{}N3yR1uqLe~W)=_D$U1^q|A1-p_Zj{BS zk57q8d{0CFO~!{1=2q$Gq$))zsTw|EVN6?0p_nzXUivEmU>bL8#d|79YhGOx(xj%s z?sC|YM;+9bIJQ;$WL`WKpXR^e9L6bLIuW2Ly>duyZJl{>Sk!Fa-P(m3+wjy9(>gg{ z9}H0kL9C-Vjf2G_vclLUZAbDa)T}TY1DHu44uw5RqxXTaW=`)1eby!g0Ql6N6RcB` zlY6J`&l_UQvfG90bZJzwo}r;(kiSG$KDyr7{CP^?PNA>@<&Fej8nwx_F`=o z>{C-yf06OPcK3uE*XvIl2?EY}*&WYPc=-5vUOqnU)2C0jwRR4C_!_jnGr5&QO`<&2 z5JIUpO!pnDe#cMg-rZ}mvL=YL930uaIvRt?Qfttf+sg{O4|AW*{8UBEcP5br=7+6Q zC#G(4+Y*36ZRca+d=KOD^KIMEXoI_VUsXDd=K#Dc`C3_|U&zw2 zm;Eb5PDSlsyys}N#OT3s$HAgP@)vW`+M#Is!6I_)?g-v_p#n2$_eow{Tpa{A`A9M| z&&3&czp-ag_1|U-_%I?v^dw(-u<7BZZ}na3^28yZgX`ZiGNj2-;WD4UuBd9?yLS(T z6;8b|&YW7MtCQy4m(yuRsfjD_6irf>CJsF%_o3C9RE!IWXf?nld}k1rlk745?bZP``LX8vb<)D^9h?O`&?OT)yn~9j8ToI_`t6=`^mi z`*uUQFe~f3z441dyM?m9g#X2KoLu)d6lycua(Z#H(LBW-UPE9>=%hc;IPSY4QRg4h zq(#~qA=HKkEuw^J>56sm#s+ud!ua+lAA1T()3NOo>g?IGgTC^7dj zMJ_G_Z0ZCGZ*Db#FzMBqgiu%9J2d|XpV1+@y;m8Q6zS-9z;S96~{%g1#Xbo_~@g4v03I^yFtI9 z&+dYCYF~N2j@#z1gF9=dI$eeyqt?lBY4)uowFkFMIW%i5%4o`Iyg!F{!m@|fN#McAx< zc1i@M{ouiepAibZ%m?OY=W!jP8afZUUnEQhD=CeX`9^$eYC6a16gSQ}QLsY&w*0H9 zKK%S{tx8OcUMlO-!oq@kYz`$3fCwmNy}h?UnWJCPm(MDigC8_@Li8>4FAmtd;~hP{ z1aCEfQ#pAA7ZVdhPDSSBJ+QR23{}W_=28c6knh?x-Dj}Rm%lZ+V^XTxt;+K2>rKk6 z(F5+1V@oxX!1G2c9VttO0sFDN@e;n)>4}nm|NQG=Eaxia8^9cViHtMlB5Ak`V-It0 zJ(sM87xVfS_=VZAMpO(-IKqXsJu>W#1q zzohqo|JH6I_+>F5zHk)oj>X+qyDPu0n$5@! zY0WhI9#}6ba*$h@74^Y=Z3J6V0VPDD`*@g9IZhHybFSZg*Cmhd&=0Grc+JSV1lJ}zOvZnaE?r5<4#0}Rn*Tg_Ck4o=K2Hc zsd6)N=9t~UASi8T%>mFRtz)H!S~*#GVARz@=k-ly&DLKoxGotd49F_-vt<_x#zQ#0 zP4;M{xKzC4xEG4JhnFjTD3B<-^$;0og78_#{n{F_t5{5S-7V6T-_k|Y2cT3#%o3DuChcu)gXKEt{&LXYZ3m0)ge0mz>l7D7 zg~thOnKs{#FS^up4?m1ebuQm1Z5Pr9sEXaBG0FG8(R%9MW^28$e5(odZEa}iLW+oE zf#%OKwqN3+f%ZutYD?n1!%76&m>tclX-n<_orx7}@~cNpJ+}1NF8+Ky(r4vI95-xkZmxFkMMyL_pp1+savPgE?pAgf>;poo zcdcg&4Vc7sI*Zw@HQT^$rzfiZz$|lkS`iL+4Y`fB`v=M;?e^vfXTavA=BqWaWn3a| z(LDEM%^HPG=iLb-_9b@O?Bo^7zmVLqSY6^`s!KcvM$~NB+*w@>%hS@bKPI=Z1NA6sQo^ z&I=SVdo)tpLQ97oQfHVoZ%*LJ&y7DniGj8*xDD3m>*?)@kSaI|#-lW(Zy9v1?<#(o z$bte`k2DAbX(M-=h$_^OQRZ;hMG?%szIumTOqw;K%eYi#Wm>#&zS4n2-@5lNs4o|9 zJcP5-8ISozLSZ$KGh4@5?7$(V&V+FJC`QQdq+2_$k5DP3+&D8o4J3+M+A&WxNMYJ9 z2!yV+Y@1O6CM&kB~D!u?k!;o{ZrH}-jYMzE{6 z)7a2K$BX5&6~h+N)kTJsirEA%-}OuWv;nvqdfd}yb@r+IuV5^G&&(e->Ax0y`SRsO zLax+HHZT9hKHx>~MK$`W%;8$j*Drz+XrDTQtGZ9rz&C1H0GEWrH{SAamN$D&ccm1R zl*A6$4VaT;KFRKMN}5h)asOZ%DEa!R`)P!H7RKB+dxD0VnVE6hnv1j99ZN$6aMUJr z@}zhYrQEv!OXLNXgVN?UjMs-UnY?L6Qcu>ejeC;DeWs8U@%*sYo7?}wv`QMXIT)MkglbAb|L)q{J&!q8xM! zo?g?~$P%igr3Fa7xy!E~W@>)$onPD1KzAE;xZmmD3BolxHnn6d*@V2riX@KLN#-|B zPoDwE)(TKsIfB!SOQZ!5Id7%l+8;k9wx!tYF~z`}Y;A4%cm?$u8~iP*Mw7-h)o!L} z5Y#mEU0hs3Qwa}7*8T=SI>AEXankHY(fDE9a>RHYWxqyVTXLUhge&-OO~UhiDMTPE z8r8Zb2*n4yHR#+w&PR%SiYLzhmwzkL_xBuJ-;h#glgCs!b0KF;>pbi`BAabM%@2x* z{IZbE+1BPWsekzsPJ5@6UV4Np=xe&?r1zcApKq99t4KpyS7jAI7_PUq3zyF=|M&Wk zf2JOOLxr}sv~(-T?>tPS;a!navVhwH%7@9%y*~hS7ieZATL14iY*ND;Udhn;oYyxo z$yiEu03`J6xpU`mzy5v%H+8i8ziJ@_@}QZi+c1~?@B5Jd(O3P_Ye#s4zMjH8EF#WhkP!C{g1Y-h`7=HuPs2*<^K7%^sV@BbsM7c zzh6D`@0CLk|6|$@cmKac?f)?|kg@-2t`G?9|KC3ebxr@PL``WX^E9u$r`z$-9i67z~zwMcemxrT3tu-6eOhsZN>M*{zKV$z?F8Ye?}bD`!WfyN%!2J`+Q#ghz>?(omA{#%0M${psf zo8DZ7C7igG>Ux#2`d*W7^4Tw1bdVALznMD7hqF_r-tQd)lE?RweER0pu2-LlU)z6-aEico( z;CvEN>Aj{exI>mKraev3*6DNqj*A4kbC!mJf8y|GFlwf8)HvnzYch_6HHy zzX?DZR>nOQ7F%=o%&@IB{* z|47#}Gc0oolKy_$)F|rP_CZLxzpCImWA~bx=mD`akd)34F8>0_2|u)}-$aeI{cOu) zL>6I`S=@8twxxx|VvNCLe~!BG`Ybb3tIbk;ox|R8V;XrzvkYWG>ng**-BD*XxnEl! zz8>69qy@?pqEUrU7$C^GBh}B!oT?Xusk51$79t6Ly;pzRBao-CNC*QTRLJX?9#3^G zjB4!3ern$PCI0Dwn<5a!fAsX@7S`PB6(EoiVagfejZ3H)(^AbX%LO{l(}7)&`sRyM zmt}!a#1*idGd(jSivb;=f|7>C=W>*tcIsT5ccP5*M-2tXL>~2NQj0qIYsg+S6tsju zn`PtWZ*^>E^Yh|pRRpK^x-B;kv6rM4hp&Emm71mb$79rEu_}62D^9@=i==&r%qton zp#sLqF&wOPkSl7+TYt6k#|2*f!+Hm=-@C~}npRS{m&0nuqS@SQ;!ldp#J zk7rb+&d0-90AC*P4RPTPzevX@u0}F+#si4lXwhYcpILLq)?Iczz>s_eL9^8WeWA zQspE;qIiDEfKQ;EVJsaqstwHa_}>0DNO_~x*2Yx2OR!M}6rd^YZY+;~Nm?b!1iM2V z6CX*byQfCkHQtX=<}*3l<&*vWV#UUdS_n|tdfK*pxOH;E{`v*CfsS@Jv_F$Q_<2>J z)gBuyEGSt29)(_LPP4+~6EMgKvw#(6_itO?YXJk>Tz*BcsPLZC!m>KKPS~#TS`sos z1)(os{2-TDu9IswR(-=~=dCrqzpK_Gr=*7Z91V1=opk30+E>?|W-dG#Jh)*@a$XTY zuIWFLh7xBHa0_17(u!nr{hsGTk|Ia*8dW-E18pvQXXilLQn1GFl#<^1|ASAP%Sw<3EKY2CBCbI#v~*d{=t}$*iHw7N!*Q*s4{)SA2o<928Q#t7Gr4# zWcMTZFnuuoTcqYFPQJ`-Zu9qr$84#$v@zYP34Yi zg~CQ^9Ycf~pTvRyaYv(=@SvwtH`k*8CU zqGhE(45As2JJYn}_R~lIl{$+w5cM%VkM!fYjSyo0SeXPWABNa4O*hf!j~EJ;^?(z< zHj#~Zw*!d)6Cb?ARtmG%)!v^tlKJxe*8&gy{481FFINtBYXb;bG_9mPU|I6h1ke3M zUN1RdJd|dBhUH6Ma4sOhH(>~%$z8>LJKnYO3X2f4SXPwVz|jy{1NOTQ>&|Xu! zb+W%|pk!Q+DaKSr2O;YlL9cC8i@$SBOH1qI#8Z(3S@egP7(!IQA6_Ol{L+-9hVW4i ze{es~{%uMBOTvqbXCUb*Ds8TW7Z=zQ)8kKJe7`3~bFuN$LB5cZyX>-OonxSYWvC&F zh?ZmRL-ZWDyh@9mkql{NORZ3QCVewAA=t6vbBdA%Fx&hy%$_hrNwvd06eZcG?JOuk zR1uYqnhwv*>G2?xGcxf<`a+m4PHokG`qW}gtGEk;cE(RtHx&)~}w@fymltBUl}1>-gL2egfifwTa%rM*@cbZX*ARntzBXE-?_>DKZH z)*CB0YBYxV3h>d4wDn=?5gG$1@cz<3*B;6%jQn-(4xm)eT}?4h?aZPE|FF?+=y4Ae ze{Ns?#OW&*B8PZ8rm4y>Hc>!+rB9`Y7}xRhWK{{|JhF^i>LZQ~&~dUt()nGH@s?Gb zNA($bB6EV=@`@1}!f(}C5Z1aOlh7%uG9B?aatr!!b zlMWobIsHZ}6%~DP zq-&?4>7KyK&db-M_-kWjvl!%L_mrG*6=(d=X?EuSy5Gg#`V?o_zWYV@xICK7zaDCj zETRQB7~eht>0VjtH06iA`?Rr~99qQ`d8>DR{V-pC3sZLs1Y(*ZqgZ8Z*QqFp=}@$0 za!YRliS~qwqhnLZNi7O-910U|SWi55>=-+0j|TV4_|Zr!LBU{)17*2TjQp&VjK@+@ zRY^vM_Ne`aJeP#qCv3g%B&ol=+y^gF{={}`;|a*Vh^*pK4;wIqK%Q7@PxeM+nW3f! zij5`H*46&x04-Z3nQ|%rkHFME%I}wJt*UAQj>Zr(=g<%cN0jy6+SI}AYex6KzGGY{ zwzG~I%<|*P`$z|=tv;w$-R#rleZUP&<#6aX=6$BiFYbJF9Y@8NAZ8OU1z_Zu3hFa5 zCVb&Lww3dp#@ArAn;FL~#Mq!Pt1`n(<(h!ORUlmfxwKw`AVb={!_5si`mG?Q4n-1Z z?;*;4DQ1MRn$bcYQGVkxY=?8_%s{)1n^HR~Yl6IUoqSY8QeIx33arO|D>E&WTl~h}fN~NKFy;4ZO1I};q zyrVo11oB*s(ynC)E$g{#uWlm*(|65-@-{~Ad-ZD%g^4xa8mXfB2PX*u_2{3^sJ4A# zw!JqHS)c=lOmeEd1Lk~6I*J@Dtt{;qO3(Q$f4sVmdx};;)OwO~bTqc24A?Oy{=rbp z8IqJ?m@SFkmf=E4r}=@Ui`Qly@<$6hS||O zogyml%Dw4vfWBJZILtp8Sz=mKIH0iD^5w)CNH=#jOaBtw%zn!Q2J)fB^$WTWV|jCv zMOq|9S?J1BZf+~4h)o&M$_aB;1N+a?1b+$DSbbDj>(2yqrqPyIA8b?=kU2O`Q$$fX zT|2zwR)&I(F)*x1!`FLe)|c;47FVvO4rnT%d%z=K$9F$(3>ueEq%pag&S2VOm^$6= z9D_gh^9B=0QX6l4wnY+5 z;MS5!i@V9W8}2Z7>eBf3b=pjjWXuPbc34l1+&uC?!rsa;<)Q0bJ zmWeI60++BPzq^q0;s*1gi7=9Hpcj?a`sn&X>dap5hx9j)_h(WV_N#68bxQmo6+0qR zE@z+rntW4h{LZ$osd3V3&}w_Hd*^0V%&CRZsly!SNjEt90R0k&W9#?|1xhHj0~ZUT zj+o%%mh0sil@ogVL}%Uf3q46q^#>O2^QE&Fnn$N%>Cdgao}>^}f)PhZ*}`1+CeT zcfKYY2eMGPD&K01{wI(FA+_mQ_3ntQH$kz^o@Mbb&oLv?ixALa*p^xI2C7^zgdT$X zw&5G=5>evX$#OPlr_^muW}k%MfCUWzl#U=)3O%qTT1LMZVI`Im+e%>r-Nfc?x8aRD zpNESU`*J-)?ZWP5g39qM7Z;{TI_T>I(vmwIRM5^Y_fQH-O80yShe=F-ILD%j&`^=- zFh2<4!Z?4GOv-D+r_qM>#`#L4;;K5MHm@Lo8&3?n*kIbPDtv<|>+dgQfW-<P6O*R>6k`P8tCW+@I@|ehXs!$1wfkcSWW{DF=Li=kC0jIKtjl z*dn`JPR}qFVNvx{1%YLr0GM(G9a+%(&d>1vrP4(92_GTp>U}mbC(~QOZ>`53ehSj9 zS7V(vTI_C}riKUuR_uoSsb$SP=1K-9#uO}W1YeVP=)Oc^Dyu%Q4&Z5*lMT?k;iNh< z?WXoB%%JF4MMmplv@=Z_Ksl7R!le$%+ref`a;MNYuC|MeINXN>hQIi&kp;#{$xM8J zl0!LtTfj2yos9wJD_ce$YcJiAlLZ=4sW3bU=tI@Kbkql|P)7~(Jj6Rcg$R(-2eMft z>i25CpCLj5U;okHmWL9`OnA4FOv})OkW_ynixYtdrpo_>)f0kKMXV0O>_$$wh4MbU zaft!2Wn1+&&)-WARTFgSRIHM`esFv~^@W)#$jHn0ey8OxPo1V^5LvrD%Bmt_H9|#J zTy7MmdR?lAbG{|c8C4xLy?9*{kIx~=c4=4ngI2A9Nu<$E|wVA^GG+I zyI{h%<6hzYdu6~ibqPgwGp7$gMnwNu6$m7TYSD;BLy0oeXB#g%3*6~(9g6heoTT8H zfE+FjI*D9J+_;hx|6!su{$&hF1yho&7r=Q5l3w^+c#`wX+5DeRPKAQm9bcz~-O39r zko2HGiswJD#H7twC}slNncy$PF=TMPIB-8G-et*RcCn``iJb-bb2oGm<$PQ0X%T?t z!bZ%ej&&0%sc|4&0LK+>U*3)f^n?D7_T~AS4tDcO=YMH9G8u&39((;e3+D{~)S(K)Inq_MDxN{d98-I^fHh2hkcqxbx zk{A5P3FdhkF2UGNiE4DF_!FNzQ0d&QvQ>K9zy5$RT#<`AaH{bZ`Wwd=PLdc1z z94j8SE4Vb6DA&Elu`g}j+_xe~+|%4MG9-OXwar~{lJoRf zrV_d5Ye=gdqh7-m)4J#S)aN$fszSxrv@~*czTP@5!qyQsfj9hyde1#Z2cbXpJ8Vsd zUYAR?2}~3M9D8zyT3Jwh-M;gLTdWIxpoTE-ekhEMpnf>6pWqUJ8O7{`Y5qI}2?WxC zLzEkCZj`&#s>JYHiX12vD*ki5=sv^Znzw)$Qaa9eAk_L?(-Pevg7?v!$Pn&!EqAi2B^b`13br&9VK08ius|r=Xe#PKWUXg#$lEhRx*MQ#HL=c2Rb(4? z)5FA|}=>I?v8J8wkb;VX-^|Lmm4V@BAC+70*YKTDrfPlK5LJdSA)+iOD*> z=PPV42SA3V9^Hq`{@cKmxFUqzgyd!aQ|W5j=tM&tzady-w<nr6 z8{p?3v$wbKs>ecqjQTG0--@s^L9!yUmZtsX@lB}vmq8v>#OfNFmH;e9WVzT&rj-x( z$v;GZdg8^qHdnu19!R>qs^D{)%y%dIkyQf1;zrGZ^_L>x%7Mp!$9A{U-NTe2}(_dsP|`HwT+%@WjTn$ghqw#*(RnCE=&a6HEF zPSTZfs%t( ztOBh!$kadovAD>kUw|lmXwCUL9zO74@Ie$PH~#vJOql^FAVSCn z_5PpGO|A=HPOO(--akbL4{TA4+au#s=8LSv#NYTLKaR50VRk7u>!^M5i2zz|;H^uyv_NN7m0xxJ zsRAUhGCI0S19A58{?#i0O@Z~c%_7%(ow0ZYcFuKUbFd9d_$~{q)BKw$xVRAPaQKO| zaNr>~{v>eISH4>t*A%+sJ&%{&Q$zF~+YbuqP=9gJ?k1YpK@`~Cf;d8f!@0ZMqxev4>k$`9=yuT%A#8$<7F(w$1<@8ajb|v1~-K4P{3Io`^m8}2_6RAIC z)F3xDQmjOlD6?mv?1=2&3G*MzUjk)Wa<4@~7)#?}u8LuM>X7-TPLe+zWCxAfs~PXz zv3!=q*J2X`jnS7bcbKH-<3)pb4nDbVoCd7&82(EiMz8yK%fZsI)gRtFf3@Yp;LP2VZ{$au{SQE-=_zdnf+xELa}rr`+4~Xr2cr61 z+r0l#WO7P^m?DG^x%4R$&oYbj zLoqc=$+EQNnTw8^WBXG!+|c#j&Ci+QTSKoE#_Mrab4E2*DF}o%xPzhKRtTk!HCJ8h zzFQVL^)N8Na?I>bSV7+NYv0fChVoW-QcsrsyatGZcBqHV!wBZlBH*je*=HTJD#}zp z-qI3bdpVMY&YSWAP7SiH4ooTa_RGzL*;V@DlsCB|=*gBxzDHm~ruz0_$Y!kX-r7-PlcWuH=I8Mup`P}}gJ*y@ zDF$tvuia2!Dl2!`bCooH5Pz&qB%1Vy3jpq-bSEdS#(N7Sh@*Ay?>$BB4a8R4BcDHi zevXYT!_dHd+Hl0bC7rGo_p*!|<~lF9TJVg^-0kZyn}|&ywAHG@Zg3#(nwZ#KFaobS zR)ImH0rQ23DSPYXBi1BZ9$mjCon?@;;V3?838YR^%ZJR;JoW7(kj*Y)as~KNiPW(3 z%!q%$&_~KJzpkEXPmcdVh%_VR#QJqLyjA*W$794k+~8#CeDpm^pu9ZN1u%-RX{9Pc zY$5)cNYZ^X%ug;U)q9y*ux)MK2RQ02^IMN25gXayu0Ok-$jo}8WYYaaw~m`g4h~0q^k^wUS z^!t8SBw+9bWxFQPnYvwg#*^6dTHTn8-1938N%Ok3z-nkl!Pdn2F)<;lP%TF>-jv>D z;$9t^t7AO8&J?U8U2Z4=bsKS(IUO=?R`&jh(Iv1+x4STJcF<$|>R9JjXYBTgUvVw~p-M*8j zgK8S6l#3kr@Q@jN;YGRgFl@J~5|#$k^| zR6zSFf4cW}LRd+oujeZg7rD65vr21{6;m@Bp4JsjnutZv=l#u|o8Q zd;nNXI~C|_db+v*0}f^F#rBgro`FKnX`!U84bY)|Bh2@Q98xN%zO0#lc(nhD#iy+B z6VHpR5X@j=+VF-`(3SLVD=)WqQQ{csk*{E|-^2Qqb3l2TY_*U@Y^R@$F0+X7F?) zydPt3uB8Pk+w?Vh9B_DM?u9S%^9V2#_R+s}yTTP?MwTzi#n3=~xs9OI5kpTH7JZhf?J-pt&aFMTLD zlGLb==oc(PcKrMaf8=((tj3!nsn2B;0jhL_VzavaQg~8f?8zPG@+-}G(J$3Ol?Q56xUXEkzyDrdE^va;JG8F~ z%}!v5)-cVe`p%!)xb)Dl(Lm!it=aBaOlIkW>@L|KhV&9O4Oas8@{o-U6;WCcH^vkm zMfloyM1?&?-c)+VB#cw4A3qZQeH?Tz4sQE)g|W)r2Gb2a(~}0cSFOzT#K}@YEpXrS zF{Ubh2_7TFS$5{)WtTe8*s1Wg&v?y54p=iOb%@C|h1<3<+0nHA;~&^!1>L}jiDqCg zM?;dEG+@i;&YtbhsyryS`@WaJhuo(S3&ZV5DMs--nNsA(gBP;T6Lj?#CU_JK(!rrs zHB5}(QyZ~kn%UoOHciQRfA*o8r%`xwmDc2{aqC_Ak39unPfngze~kAoGiySm!MNUd zv6DOg6QkPT;~MT4j$!mr;|pa+mJYZ7^f@7M6iEij*TLE$rTs4KO>|4b| zA3nZm_DPb#La!9+COO`zcGjK$r|$wO!fX2N)rsRPMECdkl*z8mwVI7xSL-Z$Y+7|+ zu7eWapeTD=YXltrU6`wJ;3?hF*B=%R)y{Dnn3X)QDbl3%S&JtLyUFj4QJC-_m5nm_ z%{|8bdbXzoCHdIg#iXRN(eQ;AUCpAy$?`j&x4B`SljKAt(y!gED_o7{2@WM|E5bXY zLA5TAwR`e1gQ^_N>Gli~wGuwk+a~pWqd)yV$cOj77ZU+fBpLt(I*2hh= zreT%L*1-$oO*%}hU56l3=Vr=^5BR_xitL-;SLP;Lv@@H^@Ib!65A?m*E#RuxGvAxf zY{MR>jw|e-N2*9?VpO?1JIa4nHm;mR_GNDiE!4}OJ+@#?^p29ZCoBNH`On`4SY6pB z&msLxBjk6>Umu}&+Zd~63wymm9M3dpTpd&*tt=W$6ex4Tjb>(;efGHavNz0Y4Zz0A z&eI6a{$;m6evyp=JA!b@NYkpJw$O%27anbRx%(Zw3DLVL0RkDs-`>qz3@ez9qzk?? zPYEQdnteQ<%Q^6?|BhV&uNs~mb^>y=M1u}R`{E?|UHb5PYY7K4WJ=*h{s!YZWr1mT zW_!I9kJP$$ws#BMA0`?#Ff{ZgfZDkiY6hn;nVxmU^E>tW2K?e+V`FB*Q|VUX6ZpqCi_1=ddBww*Y~h zu$N$GLs#&akd-~%3DrF=+KA}FZcv$^1g>-75Yca%$^4C*Wp)xti5lo@2`bk(BZ}Ev zXWB~!!r+^ud@*fp=ijlhbHrK}@0=~0xw{@p@~KPg%*n~I?vFFs-k+ujOmTCdGKh1Z zR1%Jyi?p`d&df{{Vi8Z3$@mz*rS%08IM8{%n{uJcV!~!s5JT{t@liv9N4mA@S-`I2yl0$@;tXT6KlenQJXblh67LZfR%9e=PUWoo zDY3x`e)fxoOLG;IZ~FGwzy3x=UJdj|6PUe7=-n#eJP(-?ej)H%3`8vrturICw3yCyZ;u{cUm3o#|Ggs1 zN|9^_@7o^NGO|P+q*KDb4sinG^Q|f4qPG0hWDj~DU(HL9FLfH7vR7bi>kla2q1nH@ z@V`Da<%gWW9)Mh5*l{R4h(fb2P(P2~AP$Q>9ivM((E2^lbzruo{|X{2@_Rs2f&j~L z3cp2g3~xlCgn>i~BjnM!+%f_UyE6V-v}WjGsrXM?%h~rmY1*rKHu2wXq!QOv zAYq_?bM_jWh6io)^BZHuv?c0iI>@f#Z^StICMR+2@Om}n7>;(s^Sz93H{F*)5LI1R z#&(3**)=n|@yg3=Z-~7nnK@4vuBz`_?@_(KTo2cHYK)$fmb@}hnbrl4ff^U0sF>U- zp9>tE!CEDpLo%gHX-p0`QwAL4OJSEqnoilUZZB)3<#0});h@TNAavpS{x+}H%#2nc zK>~SU_Hloc@BVD^lyYv`2k6OW3Tu~zw-X)h_O8-?)ayT&o*^nUes|&FXIC%ZNN>Ep zCHNZ+o|d|pm`m>%P?!4}3($?rbR3CZE^5u}=sFHu=C}&!@{OuMjs3M2eOmbaw= z;+m_#EQ+XrTCc_KtHjRN0-;!Mx-V*0{5n3D2KZE&d|dqM3el{QPp^s@!)!0Z@B30q zL{iQ`9v#jeDI)sLQ)2j%KR{Dd;KrJ%Tjc>8gL?&q_napCZ=kIhVIw~o-Re*WQFnov zea?9n0s90(^7@ZUM|tZb#4b+S-%Oe_j4gg8T2ymSJ%1Xue_AYF%R`e3jecv*?n2xC zu-@-WT1~9QP6p0Z1=du=yc@Zv%c)kxucL}g+B)bxu~hYoiE-XXW{MHt!vHX6MlmTGQjy& z;YED20<^i(eQSB{-B4vtsC6{oMah(rcVjn*OSkAD&iwr%h^)`wV|-edIYwgYwGr!6 zpBsB5!{HA_v)9oReh6Jc``Av`etgrjG8T8q6l1xhU6iE@J zk%p{_NAGEZ?FZfc<{x*8+aa>@ zQm!Wq76`Nt+U$F)%e#GJ={2qR*J9@tBF_%yC+OHo+^Ky&o9;Ba$3x(%)jBPc<2p>j ztA*?tac#~=;4>!!(i(hsLkqfMV&%+o4~`E{Fs^%LX(FNpO@{_4bP%s7PivX|zn$_h z4geP57yzfJnNLB4=)ubectuh(K}eWAn_Ip${t2rgC%G#wCplrnfOvDldpB7mQ8s;H znw2BL=b`ZAw$Hu?>ATFNVit|BD&(w;okl&GjL1jZrkIy-vJMPfQAl@NDEjFtY**`L z)SQ#n{dwW)dJT5ZM0ngi#HnGH{QuDP7En>OVY~1kD#j~Vh(Ww6h%}0b^ccjDN;fE_ zh~&^UsEA5Bl*9l^x1clwC?chFr+`QgA_GJ7-y3+pbN>IFe=V0w#o4p>^W1q|*Zu4g z$C-{O&e#^G#;uG%C2?L%`j4WocT!P<;k9u`ir^z(%+{Y z7vPrfww@U*cpR@)G~nHM0Qf14zYQYHcPBk8>F~LN|Fg90s2L}~`N(tq0;*C>K0L}o z7N32(MCzb_;=MEYd>v{zkqQn~Lny z5~-T{OV{;99er6J@n27zcHDTmbfljfliuz(pj@!9nMF(1i=+i)M{3)dpdmxCt zcU$9cSlY}hw#@MbPJ1Hyykj{6toz(xgZ*|k*jOe-ceD@6$bZc9JPF50!Vo@w(pyo9 z|NgjV6^#voJr7wKtdzsk zGOPaircL{ZQW^r{=ZZaY8MyKe!SjJkU1%&N@MKfcN}x;OGiFq?=;iI=L&9OFev*dz z>7(K7nsL?@5(E4Q$8I9G+3(GpzZ9<{8rX=9(TJ|K=E`bs3^QWI9$3-A4?~9yh)q3E0N*arV77@K_`PYklEC zug#w4arz|&<;sNkj#b2oT;F&OVU1L=$JOxDfOl*PH501r-#!vL$Y(r2YItmx*NF|D$TTNiJlKJfs(gDg6trH48 z7r%4W<~L~?-bSps;0Dnr^1i%&aU$w*JNZWlOWS;8ibBd>lz4_#L+W7aWkx#_?Se_{ zb+%(?@Y`8;@(XvHBC3+BHOU^oUVP!}>|5liTZ0;SRBY)V+;Ao;UdU9W^wEZ9zt%&|p)q`76$kR{n!h-+=4UeOPo~u)woxtMcc%X4kx=@u9o~p~zEENI6}5!rf|pBP8q0t2xcuL(`VOh3V4;lG~_I4?Vq{ zxksAdi-tRkuc$H$#T-N#vG2y8Z?h6CfpY>eb-!6JJi{l>_k3I>zZ+`4&Az39$6|)m zFSYH##g3iYx8BWE)NbRR!#WA|#1W_`f`7BLzV1C(6=|vTiAW<}#S8|;vAY~MuFc19 zu8q#Mb_H$_Skp9ePB%WZhZctGh2c93VzzmsWO9P4%qLNoB&&g~OKoXXXk|OUJ)SJX zycpv;SR9Tea0Z57{d-E3Sz7Hx$9q7~K=j#J5o#zKO6J@uQWlCCL|CH1xv}%1pEIw| zy&is6@?SGW{U}$> zg7!h>b4wIjY?|O$V$&J*B!lL(?@oxHi8t}YuQ@2bjCRT_j^c z4advG1)y!h4TjF1Y~B#oaS}Ga z+Jv#lqFIT!?Uf!RvG`a73<22#N|ABXhI^o`eH;hj|7Ct7-{cK4yeD|!5EnidA}@=p z&#-?1?;tZqQa=&=Rl!Dd>cO$CQ$nZG+s&b9zWcRcF}=Y{O-Rq~t|CSzg++jH7DbNH z8)po;1}5C2amVp;rfb4`J8^3fCR8QuZg7(AoE>?&*SOv4%b9Ri#WrY$rHe%MH~N{1 z?xyMYcMI8|t&5g6N<6ke%G!#h-BTIZpss@dO?kPd-flHE=h#k-dK$E2ekZDRr1OjO zAkLlVf(|j;cIG+jw+nl42cb7lTw%)bWU!vIV~G>bP-a;@B95J!1CkT3`BvdD%2g$K zAvnCE=}K-RGx;#mZqA(CF0OIPMMClGgP(KNE?m8gfmDW|E3V4Tj`1>89!SaD;i}&h z@>T8NAv0ILxY)8e9|KcPq`c)jBXjzI1vD{Ab^t;|y8{U7xx566DL+_;H*4zeF zIF4!Dv8|dq@9Z7CLBX05(XxqPH&etqDU;(7XVq;VvAsnmy`s%beM4P*q(#l_4YUC2 z-{oDiZRt@xcThSao{RYreRB##{mMX#^fV|t!%ZEQO80x4YWEV{U%eP{W5XO1HM?;U zESc13Q=u&Us(=Mm8+v9Ky!Ywu^7T{(+E_cqN5G{kmFhKqkSe<0P;%{P8X^hWq=U+{0A z9Ye%(1j!#7e5Rc(VSWdHP5Xuw;#T4U1bhDqXxSE+CVGxvM4IcnJH~xsG|+~wQZd!% z_?w%UR)xtJsCnWG_u6i)+kzb zIB%XXh&=7|20-A#ySLE)+J%Ke0FO5>%D4%Z%ODhfBIqA@jL;mV3=z$%(6y6871Gqv zbhl_qOnpw~8e3c&S4(Yti==t#-AgvZnixjnO||VTw}zhUaFR$j`SL)S<0zNh@5;}W zda<7^qs>P`!tJXKFREF$-}lqgyO5?+3BlL49H>xF19l^2&)?@!_?V@D=y=SHS@8)l z52G3rKs&ThEZ^-Mz7>t18Kp&uKJt9-#?RbpR}rY^(u!nd!cK$#$J?^f3e6)pT!SPJV)bl$;C_>OOuH3&=MQH1{yami!hvdwE$~_qN^vMkV+wm#go(&2@wDRSy1?X6yjLge=If*U#LZmf@ z(N*&P-K&|1itc^Z@;Nt@$qtf>`gZA$?AM;0k6U7lP)YEFAD_KK8vQ7PpgF{M0^(f% zu0he~z}|BlDYN$N_$7*7*Ti6= z_(W*DjoD4K!_Bxj1Us%FKu`2;wl+$}8mN4*y2V3p?Q}EQ582UD2aRWYm&-=vZa}rK z<}E$}rrFOs`w++6nwJ@T;ayP_K5uLrBq%tuQ~Zq9FP2ROyq>wMH5_a#LU?k*Nr!2o z4Y^idG1J7nY_m*}yvHmp`4v(mb{{N$E&4@V3-aW}NqZ!gR3e=v3gxV4zE#YWdG4JN`z4O1v7HtnOo0z6HkcT&?<~_Hb^v)&a4d6|HetYTuvv%sB1N zTg1UQB31ZHsU!aLlVo)QS0u8$e7X>B5{8Y$6X_oZC8of)ewNwE(M3vcE}}*EMx3x0 zZAQXT0XR`;PNIpnhVl&9=bglS8V~m+q=Wf)*^bIXwt>)#WcUAKxUCh9YqK9CG@rG3 z>gi)@X$%Oq=N-nQoSODCpi@6U^qU7B*`(QiT5>#n^FU6`#wrT+nf^MV($RIk8?!OG z5%-35V68xCI-QHpki2q&y=h`}Yk87>)NqlyaEjDb{`-B9*TTD+#b1SSEt75I?OhS= z`I?4lLYv(KXPM4Skr?8{g`>Q^M%yo28jJayQw8!sW0Qn59W653QKqG@K%M=}zY^t_qYPJUfe zYhv%W*>8E>VMuZ-gV~de!KmC|)BsdErF=tN+-+jt#_ya8nYASnX+#rgbI6UfSj_9f z!xNJu+OS(66!VgnOiqX{kJD@BiGT69;MEVY;HV|Zc_DsQGJ>^+Y1rTaILlsrqr(%1 z%dOOekrg==)km0C<+6DhaxY8y==&z!@cfCUCb2d56z9#1ighJ@r&)DQP0rP|puv=J zL+5)e>&@(BnToAw{Z-_!Wn6e8Eg3Zkfp7R9*?mw7Rys~$<7J+D8Q8KBj$u?@AA_yQ z${Xv1qSw$l_=clixG5B6=`As;wRwur6m(zm?)R3Ec+;xMvL1fxT`&xk*3%nCL|Hh* z&7D1`e)(j{gqJ+ruFKD8d}1MSjNM@%UlW6W(30voIY8lzRJcrtZD|=zDVWRvgayq9 z$*xCE4w9V+^Hc6qqzG2U?eyhnTS`6p27uX_7_B11^IVDUf>|m&g>b^6kt(nTIElnD ziPQY5BGw2@?RZF!ir8a0RmD=OjK?-9ZxpSrX)?=P7ZksUneNq(js7uBj6sMZRT6|#WH0kJ9O}=RW5C?m&(;F9OkdqBI%uiV zA{f%xeN3x~H)6W_c4J1$O?FL$Gq8Z@_t%-@$$MGx6;KoU7f%Xv=C**&_~DE&0b^6ySjcvs7wuiO*sFrk^|g`Q9>S7 z1yz1%pSKb?RY6cGwRk6Wh~gW0L&WonQ(n(f?7TodcH2wCmPgV)p*DFakGV0 zvU&MsjB8g@xkE?S^|MF98cZ>*?3?p#grGPP2Ms#++4IPqEfy56-x(hjh|FYt^w7qr zXY>f|CyCfc704<~?04F7$-y3!uEO|m>q4~*HS=(DHC@ggRKX>E5q1Cs!YgWysU1ua z^tQRG47jZ&1BL46Lo^F2@Wl!I?+PUpntxw9ZnI8#gHG`55#lC^rIVzekWpTslQkKY zk)w7gy6v;B6)5~l41SoY4!JG4c&ua$HCF{mqzw<>ByKuLvSRAT%-Ap+9t}f9Gx7yW zF)Qx5eul{Lysr8M;%E6!O$O{KX`i~q*Lf9Su~s&ZuI+S@beC`s_Rr=rX9Jk&$Andg zE_)zxe$el4oY8_Cbj)eU!*1_ZGH#PNZqQ7L^SXEYHgtPI>wlthf~w!IE>bqvrC2Iv zDwEEhJJ-Q3xhP3)zNm~nG*Rd1U8cp!<5s3p8ZCax&uU3tOEpPFd)~ffVrs5bhkO3( z31zW);<<`bIpgpL(KCiw8VnwmDT9*wmJSC+-WC1+Z9!=2b2RB#_Q}x?j2J!fhKm02 z8U0$uHk)60riP=1b8!a#PC>c-hqxtw!4+->G^zE{nPoMfnHXQF(V4$entzEkzy5$z z&eqy7`1x1sYlFlDD_2R&TyaHx zW_Y>BHA$tTX6v2ciw(kDkxT(GpFP#<4;-@-MDdc2R8aD{b+69k*6rKR@V`Y{BBBUC zKuFV<(?{E3;ZWU_wMgxeuLZnntn-MQkSC8pQ=IdN)75gFtaOcxy1Yy#kFCg&qQuT4 zsjeOyLh+}{9fb`7gG8xS?nQCNs5scHRLE3#Y>^+hXKCopYkAhfr=OjTdy=zXJ58Xu zX*?)@r0O*%Qp6=gz6fW!Key;5iG15~z&E~iqGjn&g<8|6l$aY9-v!(6CM>u}#z~&~ zCOSJn>S-OJ#pZ0Tov4^!*2$8lVnXvDng|kGQZtWRf!*WtlMoVU>&18uNqQ;8t$o>Q z?;Bb*)8D{1Xo|-I{damo^-_rH^$5+Yk9^?u>-B^AFAKhFU?Ik`|t5~ccnz!&BuU5gpj=#Gr>&Dl^ zh5dxr?F;5flsG>f}`kz?cIMxXSJ@g54&sR zLzdS&EU(kQy3^?}V@0ee)#V%hC%Z>5w^`a?I)B-@NFCjz_D$%2mLMoM(%9v^*T^e6 z3-^MVKpVqy90`oub!6>5Fx{M94|?{L{I6%9GpL#Qx)$-<4xjjz(Eq2&J||96Z#ej( z=t&LYy?e#6b1}-q)j8$$Z=;2-+^Ek-U+!6*CapTT&Jvus*NTJON8-qYIf<0Gt>VJT zF*t~dBh=8dCkYHz1W4iXr2rX+aXKQToiqbD^M7NGC5%&@@o`XFXO04BKTS zJS#lsoIDk8Kg&AjX1H8P<1qXs@%=p+8tb0&?Iyrg9&RNqJcQ{G*Mk~`l#j;8p|Hcw zXCkGM^VP>Eo1gIxZ`YsOW%=h2p2Du@H$F?$+?h>$9gqoRX7%dRjr=|6oI`i02J$lL zWm<|@3c2Oq-A!Gv?JHRPCRDa#wiWIq`PGpKmgYgC8+Mf}43Twlk!|rKWt05g7^d(F zr{2`WbuKSIAKa?(O52Dasb7koo{{oe(;X_C*d~>;-g4x>W+cTDAHS5X1SWO+9RUW% zj!+u%xJ?^E(uL9w`2tr6%xea<_yqpVc_h=pGh%hKTRG!tHdfhAkyLX#IpgOhOY4DZ z#yvT@Y+-%*njzW{smG)x-R5+!UAq=9my{mD-gFt12PF{(SwkyBLm8jFH>Gl%7-cFJ z%PAATqq8Ge2@>{7#r>HtUhF5w8amSqj3b#RU9XzQZtvRucDn~q?gQn5^c5dWdg;ui z+&KeM&kzL!we3Qv6W0PxWOA%>gQ<&Gw|UAb_U1VCUKWSz8d)iUCBV0#^k0h?xS z=U@*o({EA~i&x>{!bI`LwjelNdnl=FYTyMN{e@NiDcan{b;{48tGhP6dclXgp*1`A z*lT1Jx~~(Mo>CF1@}r&$T*gGb1CXZVQk!rN*|Fuuq`%w)e^F#dV(=&Xrz0Nlq&yHz z`0O0#IVwn*cIfJdFT2br5Cc>7eLJl#^Vq581gfF)MT~_PZQx8Dq_$)vZ7u+R7V}EG zZt1qp34{fXkM18DFdp6%G?=t5FwMA2m=X)7&%68)g>K&KxqZsePfY}W8DtzL4Puf0 zWI#Z5W?-TI7RLO}ailj@^qKN!<#<5j^dO^8JC4_EQ7EXQaAE$d8B$NjbqYg>O4ZNl`qspbKIYuoHO7paYY`fG}ToVO&d<+ zac7KY8-Bw_U>?wkp!Ocw>AIignL5UUq@WF`M;uQ>_%}98F0;Xryt~)>*@1Y^4F@k3 zfX!Iec_)$}ZLc(Z_tSXibN@@dZq2Geh*YClk?3$8naXv)pljh2PqBf3Y$@z`E5Ph_ zcY=_oVF8fZcF-zprc;)EO(~HI{uX}-bX%(AQ5;2=52zY!Bjh3 zDX}7}SFZ<&^SnD;k+Z+(o-3y&f1JB}xVp-UMg;jprk!|>Yr+Lc$TxnyRjLudlW57> z2&kliWk!+ej*;+Bq}u2F9|1$wGRcmB028|qQjJMH18WQ0Wu6H%;+fIm9ED49AJ3ZP zJ}goObf%dCtf+xq0PVDNQImZsb&B7P@rFH8 zzWz$4+pApd%j~Tt76ckw1`>fYzQz?xQ^E@HyevL8ZoTAxzr!;{&Yao+`CmgjmxTC!aj2FSD&87F|5fX}W`O4Vwxa9;vc z3x(1}1SK$?@s^Qk!tZNUR$v|W71Al5AwAQkz1Yt;;ux=dN(r&FbwD3AwmZ#B4O6pr zRa$u+KAtxggOMB4?dUVV2A8RPW+s<)%UAaX$zi@Wo|Qu%*@ftqN%Z*VOg~m8;3tf@ zz}8q7v6SKlrqM>Ahjz6jINwkU;f{0k0Ox6kKM`S4wsBfgLNNJgJVz;l=kRrO@y36I z#B!ZocZ6~DY@lI!Fnw$B%z5ZXkSJ4t+ldh87xbTEZHh#gwvkQMtJSs`Y&>60Zb;tk zV__Emv0p=V8c+|i$3Q}HInR~(uG>J6jS17@LyPi+avWKZV1-v3PZj78&G`Ixhcs24g0y|)qZxIvYJ?VcPzXGs&4f*s3 z1S7^XMmJW5u_gesi;!8BFHE_ts0hBFSRZNrJ%nj}lP1&g@cKXI)Tr(q1r*NLMC4*W zM||m*cc~yO3v>0>e~S8Wb0OpA>Jjr1{W_4g)qO#LOx%`9!z>Lh((XdqVx`W7tEr%x zViy>?f}n&UyGa$#ReG_%m@5D7d*U`F{ozXFap=_8h68O767+hez!$lD($+xIWXaer|!W%FnRwDp45cgV~?`5=ySDc9z43+q*2{SkAeP3Z<| z&Qof4AuUT)`Q=i6UVukMfW5btE_#rCGk_z3XG+q6MfFFFR|tes7ILqjk0h(khra7( zJLJo#$k6mK8QX~Xv*NBl-vJBUhFv)74^X6Fml0m-!!bhLrIXE?Vc41?h8<(QsQD4pnTQ5JR63u8Md~3*VbR^u_Yzz5Nx!#nE|#*n*52v9jVKs_Rz<-be^W11WAR_ zKpq=&t4`g+Jn?Va;pnH#ZaAt9?~|g927I&nA`qk4VSh0HO35e-3&3Do*PqF1#rAni z+=Q^7saw!Lg${b*f^tr4S*8LJW61xa?r;9j)%wrfJ=q)qyvwcdtOq<9azrB}e)!yS zkOs~dww=4-Iw3HHjQ|i1E99dORv@1^mTegRy8FtaFwg|&Ty3X-Sx2F+?{dS(2(;t_ zkd8(j-zi5-+@irP0@pHBZUEnCG@3WIbigTkI%3Q}zov*K(hTad<=sql@oHG-k;{je z8vJ}g7uDvo6K!oMaW#|w=!F3C?0bQ;!;VwU90`c!!C6HoK3$IIGiM#-{2$TW^&PF< z&tnj1FZM@7*y!vdM{XCyI7uj&Xng`4Chbd`4`bg^SGxX^6GN3nZBD$s;HUuQ>9}3f zwy1&Xzm+Kwik~>CryQt zIv5@FRfYNlCAq`!IqxmC&>TP2+_p^_xE76vIVXZ8yPb1A2Da2$UftyJA6 z-DliyXabpe`4G4(L^5gs!y(%P9$r9yg%HTjc3}pnjey#}Mx8HMFWkl_)`y%so@Wx(h$Q9kPGq7nk?Y6l1OeN40dZ-; zNd$!97BjkW!V4n}%%Ca~+0@7CvuGh38uUGUua5rT`0?qRJ5G&qQhpM8?rw(N;R(Q| zDyM$4NB=SElqO5*f-o9k2(%Onh}7cXqk`36Hb9O8qLt~d-&GOiK_>O?3SR|ekclxv z9wBv*)F22ozSi@FdTCb1LL8DCv=qm0@-zxeUkw)n^${LvBbKRlKiq%pCDtaBw{vnk z6=&4Jz9f^ODAHJ&ZHsG7)IWr*l+VLSijEDl1RL;yh z&+@_DR0q5rSQ&0V!xl|*j%_rVq3LwvK2%x8M{2^J)fbCW(m;dmD}iMaCM>EdH1!7O zmV?2|BqO$9P%|Km80`mz6#3wDcc+ih6)wf6AOeX7fT{J|@(vDopNsIP#o$$t`rWj6 zI^{-<<@bkfbgOBRbLo0b=MeJp?2d)p?@?LXe^USH^l_)&ePo2J(o!lAOH2N05~2ub zE-iT-lq)El5G=OV^XZ6ym;Z$#L@|U|e#TEu1hMDm)*as8F3oxYu@H+qh3h@|JBc0M z652>8Z>R$<{q%78nbKb4emdn`ATrB#`UE4blxNRq$qu$o@kst}u&2Zc^qAPM#vmaO zaXIaUi~T?c&&Rz1QOLzKnRc}{L`xL5Q+57hOtbp!E0Di!`w)*}ETk4^o`iB!Qfj6M z;;CGI3~+o%zOje02&2&4>;FG72vjvlaMRi~u@6c#G=!(qAdZy7LmLIL_Qgjk)ZFmr z%q)56gtqr0%`(klW28IA{JQbA7SgS_9R<^Wx6%;ae~V@xc`+B1e~{TjIf9~<_M^mn zX+9QY^YsoslW0JUJQZy2T~s&_yE7oEvv=fW=7YoIo9xA^w4^;?gypTMoTfe9cHC)fTmzG=)M3{!AX3$Nl z5H)@B#zI-)k{Nn&VXQ~Kt&z{=6dUH0{x-n0sttdt`-DQt?`~dwST7UfF)Q?wJ7WD) z=`rvYAgG6(<&&@RKH3~-z0Q98H3#GCbhQQ!Lq#NAh+PDHMfr5&*SJha%(ntd`gBz} zkp%o#5k9DBcZAtEgX^kRvuOcW_SoJYQ7WZ|kwzz!*28ZDURJ8z-JCUn8H1@4??U3* z1&wps)h`xCgI3T#IxfC?vBB)?#SJ-;+j0y7tI;(>eJjgaBUhhk!#WP3>K|GO@%sjz>>=2ft_63#(IRP zm({g%48-5-%ZZygTdOzKIn@ygu(K`%ULEu64A4K#x?Za_rrH|gi@vdB;#<%j$QHCQcs(vwNb(EREkEQ$s!BX5bYLgy5OJm* zx7^w|V7(8_(2|4P*EakoaTn6<@LHN14|2S|Q*Q;V5Jk;1k#1 zcS$bHECA)0v-wwaQPXSQb0b1>%|qX7Krme`ef6iWM9T&rqS^Nj=gJqkaXH>vPpp-B z)Bs5@MRw5lT=xn1!P&8ZPxPRsA-{OMr94o+H4DYwWEq%hLP0eEn$Qy6liMgMj2;4)E4H53r~ zEh>~CRY}<;n|Y*^;$vuN?WM8J&5D5Y;w(;yEklNvSw{Mj0B~nGjY*pQ=2Shw4N(3Ri6=H{Nm5C%|gbURn@eqy{2= zh*bMg-|f9leY+52UUL4_Z`b{(GEPeoZ>uzojMWMDO$?sg=+tlDqP3LtcjY~6nzawp zSl;^< zKQEWd;d1!II~RB{as`Kf!Af$5H4sLvA}sPtM#ei=z03da45fNT2Z%bl1}oY==PJ;+ z63g??-5?&d_GOfsd23;BI+oD}$g5}^rI(`2_pQq!pFU{JcO9lHgXUq6;`5_W4=ooUO%^2^aRWIcq~^ya%GG+{^XKAn{=SE+<7Xc2D*&cqO_Ky(v5s5w|5uKV%(% z!M9cmOs^KsFHq=!{$u&>Oc6;wHzx@}b~?hUx~6Ia`nb>>(&<|(hMPjry>2b{ZQXohqg7S)OvHYvERabuiF%E~^ZL>C zXyos#kDMPGwRkDVie#95bZOyZt_h5@AX+)E9h#UfzE{e$Yo#}k^3qX<*{H?D? z18w>G&V^}_C0B#dLELLzRkUG7)qNh~QNv7Awa1@413i|S<0gL-CEv4n)-}oh9YnUY zw5I!eE=>B(e_gvG(Z@W@9Q2Rn>i7p1&rPuX{=ixU-!^4+v-;sI>9utf4EM9YQ;u=T z{ARHuP02?EnvyP0&owrQQl#`MfHkt$l z!!$Srv&<6CV_d5ntV3Bnrr)shiVQCJ2BoW{Ss29|8Yf(YIi{9lNB$va03o-=$4I>V zd$=Z62df7G!H6evDRrRxs_5R_66ufGqJ6O&{saeu;ZxHV}T5GzVGw6 z`)sa%9ytZb_%`|a+oS=;3+_R^!3l>eqMJgSGFmMEp!reGcYYq8@LG!73{sc$`acGB z4f3N0Y%i=5v3vnWP?Hxhz(}X5qi&R&j{h~tIgUAsezvv{8fXfl%Emxkt7+q6f z--`3O&Co_m{T=KM-*+%(Lw;k4aV-`)m0_$vp_*TMz;WORgLl3%AF*r=$r z@>T~vvDi$p#+Y`?#u)QyGagmo^eFDMUE`dm2@C;g9I{zz|=3 z=;e4PKheK7QRkFUuFYY$X&kCzMHl;*yU6{^P~9X7WO|yn+n9aEL%Y835gs5@aZXJu zhj@XT8EeOn0Z)PJLTW4MrA0>%??b?pF5f7C(@_s|gOWhU<0TA9FPTvUvEeTDU2=J7rt6 zseZ#0S(>Um?jM3v_(ZN3v{wzB&V3!QSB!;QBc{MKFc8VLhZ+hlB)1(zG;g5rRe`JK z{C8E-X65O9f!PPNk4fFS2ZNANSqcdA=%@!!?kz!{hP=zM)**LH?gECQFOpF#{R8mc z55|`c*DMw@Y~EVk>M32gj9DmYq{NwfUAR!FJJjGMG{zhvzAt4ubo$8|54rNo-n90Gk+BUc($!wKxM{^JYo6^57sQ-N2; z2lPaPjomC9EYfqr6eFlnN4Jk^8VX@dg*QsCTrv)YU3P*qy^DFI~ZFWpvq?vk&hE^d@C>X_r zJ{6|hV$jRj750wPxrLc51=L&Z%iGm5`D&u65i`Y7lI!(bGD5TE+W7XF%(L0t9;

Fs6obn4>dlKHiLUV?_3R)>uAxi90~=8oAZK|plYLzi#F5n&aqvjgD@E^elA3@ zDEl8(2~RD*jS5uWNM*JgD~66~<5OT*T<3g8s;J1gQZzSL*q7z46s{x82lnG^;Rs#0 z5dVWP=XNVJ&1&WI`Nqnzvv6Ad3mmrNL=!>T z!0GzC^sCdiXfyhz&t^lvG5SqE2Y-_2xvDUe+kb-*3f+i#$2)E%{XPg(9Nq0k z(9z>&(#VuJd-zbyIsM0{GWgDB??t_^E+-eUF2x1O{YBec)!&aYqTT)I44Ng@gl|^v zS>O>=Pp++g-MMVmbBuiS7$DJk(v!9TPnvzLQ{&e{pDbNa_a$wo9xiZd7S1b8*chYq}#Y8MxnOm zME+|)E^)TIPaSsl-iK(v(!=~(E|ScnK#Al0FV|e`r}l*d0q}H?FaF)2WvJl9L>*kJ z&3k!F`g0zmi(|Y}VOB>cN81<*ooqXX@buD&ZBNpAw8I{+<#E?wh0{X)DEncI1FgY& zLg=mKRS}<}+cs&^G$J^16rcEc;2;yiw~b)e#`ngG*;aUtfA-?QOf7Xf6p_`d=#x~p zUZ@gaGp}3Dpi`(l)cy{}u)>cULX6}|r{#oLh>&&TGX(*X}9f83|5z_1OR9=Bf zJ1?P7 zVnysG`&{B6D>v#5dL#BUQv--t2Fo(pMYtO<*J>I-xN2$C-4KNPXH54$a_i;fU zNN%9QecyQ<$&1WhgO=QSs0FNhDITsJe**s>>B0BMP^TnW&u3Ss(E>Lh<|VctIY`?>W_+uC~Dbj{fIo zy-jA$3&o(|-Ec6Kq59XL-`gOGnh9O#yWaj4h|MubcV8_0Jn@OyME8m!^ zsu26Q_vq`z{z){8@K7CmXGgD8e%CqVDZC^3WT;jZin?srdcv^rIoATufp6#e?cBwC z_EVcT1M*+ra?&aNy9ROfpbOubVI+zS$ju+1nEc%@opDq-Ok2yN5qZiRGm=7l#n}w! zYW{)5)g!eHVE@y?K)aR8`e=x8U_1dIL}_jHrv3NF*~jz_B|OCid<}LA5g{0#f6tDV ztC`Y?;II?eJ`rsXgYd*2c-xoiU+`xm#+|^z>ML*9rZO9B+0YTD%6A3KTq|!(RM^2y zKP>7n@-Xi%7rrOiFU3WN1c^3BSODf8OzSHjl-4!5%|x7;2!zbc4#=o&rtzLjk7i#3b<}9nBf=Km$@0`|q z`|gvRiOK4w`aJI0Xkr^yI5LEikn7tZ2%&6JEszrD%S=_mp*mk5tSSg)psa5I3TDvE zwEq&^#qLc%pL~G&H)JQxoOd?bOqg19?TsugkbFv)aH7N(IjjU1n$G`aps11%{-lRf zh@ry(#-C_V1xa1gQ?ip7Osl1H(y&FaA0<8qVaug=?uxo|vS6{fB}g8h9Z4Lp5$sX> z12@GLkbpSW@MWRVVD~d1{^hCO6cT#W09J*WV65 zH+S~0d-QOeigDKaWoR+>H{7=cWX?b9!R`(RNwj(lqdYdzZ-0Eu@})S zG{SsQsp^)@LJ+@9cFxx2NAGSwV_#cXn@}__`$z7czl5?9V)pBqBYT6diZ4P)2xi?! zOI3nV^}GrYH5L^zD?51*)=Cy9L2Jj0M1h?XhWXKS--p;SC9c0u^@Kkzin45QnLkZI zCLa>ziTWyqg}hA%O||=buRMZa1RuMk>5-KQQP{GfCA0!IJNV=`s#SPn59;*iQf`PU zMrh6~DRJVmur@xMaNoW3k&EP6H`%WJxKA8~@8@T|L*PN|2K_;VDL0zhS^5~U)&{$W zWA|WW@q;GbwBWQXUW`5Ti7=F@7LFQ7nHqU}XZdS21J{dPiLs7j6fPSu^ExpkS*Yi2 ziDAzSS;Z#BoD=`xknY)S!-KMM!EcP)uW%jFeA+fPDn7xLnYafBV^#=Tu|K};$@IGf zmIzjTQ5nk0joMOhgx0ivy-?PD%yf?fp4}>=*-5S;k0hY+c8E9DW2M`h(+);zg!~4a z0hP1+u&PC-dML$Akio#Tgi*G>`eJ|2xdZ<`S>28RCiH8-!T4(pxmVD@9}^(T-(a%rpxsaC~Ku69LLDTq<=+x~92hm$yQG(ITW6K4P~yu#fZB_UA8ha+K~ z?_&+tW4JMz%0p%)j4^EEGD3v#$H;=eONrIcO@YBccj=;_eGPV@3uf)J4*9J&EFh;A zvC?RkLrr43wbFfXfCF$myM?`U52-3&?wtSJ_vhz&P5boXr&1d<6#-|=K7PrV4qh*o zSY5g>WW;<~wVshR`IW1QMyh9bL4A}5Xw<4f=XiaL>3r+NtIs5JQ@p!&YWG97J z*P5z`FStIh{3?5R75xS-%dY}U1F6|`b!1rb4H&3X%CMY`#7Yr0v0bcj5RFQ^`&zX5 zb{ts5)v>wYI}jY}t{VF9fs-?Wa+)C%q7-)C>A+j{uC?ovnkZ`*Ew;Kn0B*xYE04Zt zAEbz-{d;76@vteCFvgO~gaGir2@P5>$V>ol#Tz@QxCgXn9Peu=t3uc2niD5Ot|(rb1{Vh;Fq zc=cMOEqw`cP|b;=tBCA3BDGbgUBE9cgiXGyvEQnMQ4d}5IAOa+_}~G_iC46_<_JU~ z1^h*}Z-vTF^%&z9`1w)(r?xYo%`4`Zt+x;hmXrqmZK?w|Utfscc@k$EXG3<`18x}hP@LZmAM|^6i^aaxK(3?QNd?+7Ml$ct?P0(J1b`Gw}C~` zSv`NxE@@~oDov)BI@O;LV0QU$kGF*5At+BL)sSF1n$@SS{bq{&Yd7`D}nxvP4s_MQ0_ckixZ0TU8zUcV=RcnYgmCG)6^DOOJ84pFe6F9sg zChcsF{q-cft=d7OP-&9!DZCwev)G^{cd>bsH(+bu`sX{$JGLv*v0iWZ?^MFpIvH7P zS?xiOhPdf$sVgrhUP2pAW63~E-hr1}#jw^n=nFik!$%-i*{~I9VQQp{U2Y8+Xckoe%Zm!(I5WfyH4=+V-7^Qj48GG)X%#pY zz4f;qH&|k=b!oYi752@xDh!2ogd2tRs)4&|O1oP-&F(qli{03K++kTj_TdvxR9^p) zg4|FTi8yY0XitTg*`(ShfnT%MZhqw(eFkogluz8#{*sbQUj;V)tfzR6_&QAg5K8Z{ zn50Oq-xFV$5h9netY6&d<=dJ$x)laD&Og>Yb;5OGqQ)Uzg0G1-ztE-e z?m?b6Z1pW)ZF9Al^u*xjew(yZi`_c}IXw(X>I&I%t=^-Pt!_*NmC01BJl@jCDOzi^mnifa5{!-&&WAYW*Q;-!on^6E zd!?r!%WbZB+P|qdFrlk_H4LA~C;8`3QaB)exGPJ`uaqa#LgG3cM6=tbt=A1^hinNJ zv+tEO&NPW&@K7W=lw3zCWScy9n?UaAujffSZgub_BQg4OH62=94MQ1eLO;h`QorJm32YC)taVtJ{|`7lF1j-4mD4N zrrCrD!gzaO+CIu`sZROaw53zOt>5PGX4B*O_7$ge1l|3cc`Xowr=4+68g#B|n%o?; zepK$P^+T!J#PS}UarECVRP!@;e6k1Z<{MLEgJT{S>$oh!4tQE2G z@)P=$j9F8pns+oRx`2|cfEUiBxJ^ZllLN--;N@s>Ev+giA6ASh=0wc7ZRAWkmI99i z@1t9-jiX3@GAm#DD&CIWFh?<+f4~iJcfxAVE%zT%c z_NL7i%UpA-NCG^K^~v76xBs~Ct$J*zc??4PVY5>2Z^PoY;%r*`U{MO(sPZ>$MENC5 z)Q>CW9{68n+Jc?+I*%CJ2EQCZ%CB~LQ{3jy+lC#Q6-y>tO*!t>`m5~L9;0Ur+pKaX z*@T$xrs=hCkv!83mRkED>5`XEG)<^(ElVy|^GPN$iJC1kS-TQh(^Ry>fYyfh^6^aK zax|u^mf10Qovcn5Nrt_;k`4tO+Ku+H3o+yFj!lNOMO{rUjX@*p**0;G<2h}^Blnqj zr3Xy*c`2#R2evI}8yfcgT?ia~vf|Q6w^U{=bH6QZsthjnb$wm&@5(PX%j=&XADYFHSwZJuLjKK%Ba}5uw>+T-z*HoYHT^>t+bxN zC-(gOjv63OvyT@_#8J%Nqlg7AIEidYuMp?W2ZMZjWGmG6Pgt)PbWH`q%f#B6;Ph6> zl}s2nw-sMl9AEs%vTQp$0Ao$yxe|Xuw*JO^T%+hG43s)e25ph~AS`(#vBWcs;K~Lc zTCO@>AF*2EXB<5IxO6~bZk(6=wEX|N5SgXQ)^2rt6QfO=C30E&^u--AmQGpS9UKxt z&tVIksC^cmiO+Ga&gokb?tbie`!=ouBT-RM;5axZcyJNcb=1+5*mch%iyJh6qQwib zEQMV|nS?^OY|94qC;ty)?;TI|AN~&?qm+y`WmZQ%$ofe3YRDmEXDdmz%n*)-mesK; zGZ`U-j=f3|vd58`jAO*fI5y{Zy`4Va`}@29xF7c)J?bInecrEijpy@uU9TMIx1%Go z@_p-bx($d=(Z9AR@6m@rJq3!Ai{;2vm6EFFdi>}7Q>dCaOc_a?c9V+YJ+JJv!WCERB z%K^GXn~QtCO}}r>CQm9e9p)X`eAns+8BX7fXLlLDWOk`$D_`9d(M7kFU+Rqr(J%DE zRy=XDBti7t+bv>H;o8lLFRPW?w@CLs4ZrE`!5I?R&Ki|`JkT)uKcnX-S)-?JukD3# zXfpWSG;TR&DaDeP6t7er&#`M#i2U|{hVK=pgG#+1NVn7pQE1>oj|-tTTt4@4_4?|i zU6TO2-MXcorh92z-QdxA3%QAugr|>LcntCga-(dl7~hevx8sRnT($e!q&WPgpB4Tc z^HO5WfGbwiT2^a`~b-1^n z@V`cyNBA`pQSOOV49lxFmQy+cz<9oonbh2Nx`wP0Y-Qw&_*d@b5db=gM01HKieO$d zuOu#dj{aG1SX*rJ(NWZKKAB%sp++Hr`svO?dt4m0?CF zoEgQymf`uY4BRp3%1s+@mfyp0mj-seZPv5P0_wugl%9J#aN6L+6K*f_Tpn>qZOzKu zMpMxOuC3J+&e0R3OL|%{_Ky+l#P+plJ%q^`abYxzIFx@{l@COu?C} z89JJU!lJqjorUExzDBBXUcW&sY{G2)B4fkE3P^p?}_%j$c;m?bh zqh<4&8FdrZtTa~fKyB<7p?`@m$l(f8e1^4lkH-5z4H4`#HA5l8g zsTZ#g%((>in=Z*wwphv0kE_!2ey8Jk;q^osktyYy8ko0TN_QPSP!Y*KqH_q~hz_VJUmtLJ$< zW+ja>^>de2QmToA!>9VSzDn$cct%?O2geoNJnvA-t= zJ{`DGO&OE1ByCg$%vn}idRH!;!*p!Eu+Gvql$4TsyF!^{ZTE-BAwqWxHF!cf>86Y* z_lO0g?P5NHcd*>PrX=OZK0$KAz=}JI00JupNroD3LPJ{}cZ>Eu0fWz{BL2Kvx}8BH z7^B~VIZ2dPNml_rRL?&{@NC)psnv_5;5{|uH>X?pqr)DbK3MJ*FJ83eSVfwu4;WJb z^hp+P)}?={bWNqrRSX<(tTrpE?>$cqT?;*@xWDaP$0bP2_!XKAb6M8>me7$1C1oab<5?_dA zS;AcX+QlGt~-XyHEUzop~C`qT?T{(S4c0#3x4R;W(9iii3#)LRnG zYU%)ASi%rk+h!p3I(<3qNT`c;&sD2U=(}-`hZIsFvh)g&%{opd)-| z7$sPf=LhEO+IbMn)#`o}$NaW?_!cqpB(WJvcyi8$*;SSUz<@gD{b3bqd`|Z|lpJ(? zOdPvu8g|^l1}`hQGwXjx@M zITB7$a5fG0xt`s>pZyOyh1>y1M9fz^X)|7N#AWn%2Hab#uMKW|fS(Ce!Z9|l0`hJp{8Z`fv4M9&>XOz0GK_8s3SRSjOJ_?V!r z2VxzNjdM(}`7Q$L9kMy49M}$lW5GW>+MlkGa;CoiV*ALgZTZW;`DPQqONsKlG$?i! zf(O!6r$$%NW9Rycse55Vj%0;}xG&v-mMLi^IuCQsQ0^>$$kE@+Jc`kc3@Th9Jl&l;fM8XUj=`T7a6fN10L54*{GSQhh5UORJcV zuxw)-2HERg#vy1_+TphK0T9k9H`LAVp>m||mFlHoaz^a$#@S9TqY54Ok?vrjTCcIu zm4Cmki|>2`b+t|3lI=51SoVKHI+HC@dUxx7s; zPd_e9M~+{Wfgd9SlhMOj#!13~8wdasK|lFM z3eX`l7D5H;ILu!yY=H<#yqAu{O#9(OaRR3Wt_!&C1IATQlI;o`o%my=TmNYR zP?=PI!12TsoG|Th$cEDJsanNOCC5>{Ccx=n7zZi<2FheP!qaW<0Afo3zm`TG2byRn zY=(?vp>ATtS+2dhffH$<`}B1;WO-KCs4%6le!mb7-MSZy(5L*vWjg%)r#xvw$`SA< zjn2P=Gh1G`_0Cc=q0+$HY>knOR;b>@P8FbTs%2_n6II`^h2F8e4)hxn^A70p;gLxk z%hFl(vU7&hJA}NcP;m;&QUuCBCF=D)6H}L|=~w>iEpdScD;66dV%bUIX};lZe(|n3 z9-)s}PG&1jN7b~Iq$A>6RGl&Yh<9?oM{)+HCF#ZSdIS<%Zfu75ye7@h75Dv-kpQWA z^6vPP?aj<29pS{=?&Dpd!9sKqd|;a*pgmXvKi4EP_wL=;>qy}~2thvEI~YTWo?WE- zTLpyOs537;07h%`r8I$5aoJ&J#`pIso$q#+d!L?kvS032MtT!%#ECT3!^s<3kT0u&gQ3s3XDIUid9MkZd#?XcYLY zS#ECi(yTD2nAs8R84RrlH+1nGyZ%!TUyJY!OVqv7^7eSRX`1yZe`Kh8ryck_{bm+^ zE602lj>kl~+n(k69fOwaJ5t*XVuc%=$^6wDC%HKLV;wfYqJU)M3Si-xU&;~g?x*}Y zT93No49%7}a3dy83A!2m=fLYYW(@%I(CM$(eqMBX^GtmwJ<94ZB;2xtF=qX?uMHU= zIT!3yQHn89u`i!4lS>%-$*G$Ht|`j)rJy}Hit05hy`zgeToy8vaPtk@BhIfAd*M8N z!|86mu4Rny=<9tDFaX9PLhJ7%pujIt1NO_>YI>(zDDZ}LdTB>?O$J?F6>q>X6g9%H zsXo~vPQ|ReMGohVQ<0?}PNI(KTRMeix9#_6C@f{SOuP9|ZlwNV)7QbIG{niY3!F=7 zxe1fWj}$t){{7G===w3^oh${LJR~EPP6567@;2;=RF1}O!n(;*mp-u^dOf4pba7f#NSL) zfm5Q66F8h^pbnw^NuPxwb*bV300*iBDx3k$eHu%DZTvLA)FG+`bP8n^QHGdt;BoWC!Qc0QwWZWz4NipBnItsZjfjf zvuK+d{L#!7SdV#KyZES!t1pgjp(^vOAUZaVsOWKJ#^hya1*B6F$+xEjxP%q>$f;5T ztBSSJG|IA6ahT%`>wA6>O*84WJoh?(5MDrvgA2H8?FVgfG3e;mJHumVfXxLPF2UJU z1OK3LBWTEdC2xu>g*5cl-}*4ph~ia%BL;7GPRD@_qPGjKFK!_L&2GfI#JWi^wq5uf zuK$fJ*QO0Ilk!nC>&)1IU2U`#J7kzZl1XQnu2fu7AfvY)^^|EAKB7^6MqSFdcX()l z1o79|rczL%AgYtmG)__;Gbb!f5a}?`8G_A+rZf39Vy1AY)N2QmB|a-8fUY6^fr81q z_%4^gsd9bG=d@&nM|5DyuuE1u4F89xHy@T0KOiSz2vOhQD}lInf^cRM0--|zsSj*^ zEc}l5#WiY{wb3vc<#RJka>IV}>>qOJ_V{3$VSlN+UwE*9=;^ztNr?js&MQgXxtd)) zI7E>&bxR=RvZ+Wn%dy;DsB=-HI>SL448A5~zwT_N-7SNARy6YOnBmr|i6{NxW#>vK zxC9aAgfRT)RIm^&*5d?qHuKw|SH#LkjWRjboO{tC9w=+r#929fu!)Bo;zSte4obI^ z(+93WaD_daofi$kCL+Y>2Qnb|46#`q*T{^xQWdH>Jg4K-8I-u|Ii78UOEz$2Ah3h7 zQp4(y@73mNfGWuCFw@sQDX;xX47}nPO6=lSRgi_$fth|Z)`zRepg}Q#g@85w@YF8J+%pMqbtGl2jN*q0o+si>X z`hUF*n3T?~Si|n+0^sCl1%9__SFImf@1avdV@!}N^%(ZOkW>mv;n-TJ$DRQQWH4YB z)e6A?{V55)sZv0!x&rYV-Cx6#mXT=h1YLzih?lH|ITF&jr584`@UeUtz=tDkXq2m; zpIKrAyTr?PXqP(F=!#uzhU2Zsy|hAfp$qh|IFpY zLs|W%B<(U9tcr&0iwof_OJ`i2EW>8O%mCLV4xT5Kx)`o8!0vAmja^4uTsoq7LY=B@ zT4$Jy=uo_;WOCEENdUu}Q`%&F9R|>T|ugVZiDbBjw&1u*}hW*9OagC=4 zg(gOIOUCvNI@q~#893GY_wQc5DZm}agi1$`Rth)aY!`Wr`o=cLd@p>XvHF7}#H5}& z_9G%>25Bg;`>(Opz(d}@zy-Gs?ioc@euoG=I698M>(E>8PW#ay;hi_o4_`?tzarLv z8>{xtytCsJx&MCqI-;+5)m}Yy@iH%}wy_xuYt8nee&d}=8raIKc)lq$)pKLNC_|T! zJs3niU@f{%d1|cQYV?jGH z?Wh0w+DlxMG&H`quEhwqvUGz$ug?U+2`m!?cn9Ww=V|g2mdAT@A&PjNU;v&??bVHe zAWm22hQqBa@N@VffZmA56Qr6+TjNkV{W3}c-;W~=Aa^=#07f&3YclhQ>^wPGryRBW z%q!;u9YKjQDw}?_Zd>nwqT}VFTCC2GvXT&m1ECUN-f|QP3K)=g=Dw0WR_*j+h8ar( zkq~fO|JfDQGd{OdzSSC|#P$yyK&s=k^qek__AAJpHQTEyyp)m~>K3U?hlOgev!4}` z=@jtm<@T@c(pq8F=Sd$LqW0a?XbI01u85_r5Wa zeTve^m3qjD+MTH%&fR$ZKIYsmq(oSm8kJ;Z7NxLw3^zd1`WD*dk(z*uwEAW*cYIiD z#ixvq5C?h-EREo~NEGn-XBZQ1zCKE_L0RqpJ8a17{bNxI4!E!y-HJeVlxohvv%2EP zB7+a?da8&1)EvdqsNdJiJ@F$-Uiy>oeiS>?4oCm$i3!$~KTcv;`5^hR2OwPrF%|A*e=yaDBp=x-kOO-L@oqQ=S=)Z^aDqmMV~+} zv_%}&%fA+b-W8Mw0QY0=fGgqh>kk7a=#?CPIbEj(3VIrOYrx$jEd)|ClG|W0papaUHTM{E{^5 z^^|oz!J|!m)uiKYkYqRh-8tEU$L1KTz6!88FU9As@31Sa}ebYM7nV z@9h6{Xhk$Y8L-bE(5@4~NvGf))ryDQBIl}RmbVH2zgSc?${@Tv`x!7|rUeoOU1ITwkf) z-naEfUR*+VK`|b|o4Jkjw&;ZooSWoJ?1S z+zH1lNwQ%U8`DOK^Kkz+O3cU56sV8Z^bPrJH}0U_C<(!w+n)3rt%WCU{@M$+qdt$% z>_S1P!#)&~7Q91K!C47~w9HI*?}z?tpDx3m^CWj02`2TI94NahSSI6J&s7}nUbo^u z+wYA>+xe8y;L<8@+z@rryGE^)z$cDhbarzjKk|{D|Ii{JJ8RAy_sH4C5 z!1Ng)pnwfiEGLTI9GC&hgu%b62Lv{QR|n@_5z7a2eJgXz26N9im={%&hXa?_3hxBm zYh`GO0*{xF)$Cy8Oi8zt2ve#a^-^5pj`PpMyh~b)=OM4D4+PEqSQECaty?2UF2;Hd zc`tyTO;A$%w(Z<;OymX-FfHywzt_gs4`6WB4U%Xd9`_TGO9(ZS#2SAeM8`1>mp@7r z=TX+~Y_D+@FTz{1ZTh070M*?}+WNU-XOs4>KJl(eYqhHyPbq11{c~(pO40^_6zgCo4D!xzW?T_CiH6`=P_6YR&Vten(dCmxamWDje$Ox9!kc4FHV^NRnsQb)}!?YJ+l(Kl3-qbrY$$#51o@aRR4e(_A8lwLY`YWdh zA)~FNk_4A8q=a+jYiD-|$+wD@PDwa)=|b^6W)31jyT!6^tt~+jAmpwjON0rYXpxf3 zp7t;;5WZaLY3Jm>xFVidO!l9__->7DuC;F5!3LykrhFdC-6qzPiQb&8QpcG!6Ea>L z1X0Mp%GHa@aeNrW4`dEH&kS!3SLd9%96mEMd{?J<&@B?78sBGizcw_=jtjHVmTe(U z+-hAN9vijQknQ&VVkyPc?=x*zu6^YWLP^ULJADGmwI`idNbv9a*?UgH$3_xolmbGj1@;ttJx_Vi;!j{XeBk1i-*7g6*%)M(h`h`*;YP!rwI^rw? z3%wLQGW28gb4AtUQo=Q-TSbu_=T3YcdVAP&Qp;)mcvMArX~f?lKXz7$j?s4#HScKc zN`)tn%0sWt)TrH)8H@gw!}IBc8Ewk%Jm`^Z*}tdF`}_2__EBIMYx}%syKUpAfVps6 zy1V4*E@8V#0`XDz4Ed&U&oNtzyYsG;4HgZ>z_oJeV)vMx@ya9(EoNuODY2i+szw&P zcoBnu*ke8;$C3(XC5>Z*3FI;9p$|@pBCbA<5$ld0?-6JEa%K;RaJII*f7Yabz`5izKy8|?SJC|Pi#wCFHLJtB>Z z6h1<;t|?`f;Z>evo46HRwNz6(?NyFT(OO_*ZJEj2Uhc%D#tv5=aIXF}CwGLt>L{D` zl*{(q_IAC-__OVLo&kQ0?;=O_ct|z>+T!EwKZ?I`#_?4mQPB1f%l=z7>tBFd`|$ zECv+u!z<*T;tG|d&5aF&hJOJ~+x zXT5e~DN{R8%QE24f#&9x$;td(p5^A|p4~@$fnk&xCHee+6ODzl=6o={Vi`SJUdb*l zn;fT2mD+B*cJ8hDqu}!^K;h0w-#?ZyX=!~bkhY4M9#%a`NV@x(yt`&xLpIdiBl&`E zF2y4FaUse|PWM2vMu&IRc)v$;x6yQ~(l!S4O`el&a2we7?;kBznpdXfsz;fL@ukFZ zQG@;T>y!10Z*&D1KRfmJn2T0wQhrsEaHOQt{*D#@t$}LaYQ@d^z;ym3sKE;7j6^p# zH&23>cnn@*VuW%5@wkUUD(#R53=*VHA|8ku6(BisS0rB(2)uNs*Txw?dd2+1HXGbf+B z0r^a>(rnFGdek9-=*2p&`t~D!-j-tWO6DSL_N{XXroqIF!ZR9vUL>?U;A(15?c=tH zy%94c7SP9IN9^(ld>Fq429Me>g1xtVS!JiWgz-_;f1b#xmJXpxIGeQ$AhigaZE!Eq z4pjrp8Xb*DW@Ck;sW^M)p0+!(!vbnIM1`>|!kPh26c;QA`f+ni6~%-CDGdL4>iX?_;`_cTEG zeog>JawlToAri)32XxmZpaEKyJIbu5J5*^GTh6Q28eESm8AA1jjp0u%y)wJcd|kdF z7;wRodpk$~HkC?BJaPP;%GU<BW$ZFg}su*ksreCuz>Y zG~!G5)9tJrf*!~e35BnSN$(>7|G-Usj}DkQ+~Ja45R00jmG;@xP1CaDMzbwr(NHO5 zTmYz&9xmbmKmr;sLR?rm%UbW`MgRcxL3roOzf~A!q&w%Gs$c$+_f2idMYbJJW2JUf zuzhto(<*jE-AWfyW4B5g*S*i~h`nCy4GeR4f{vSr6!r8WZw9aq5kB2sXR8JakNH1g z-ip&gumJY3$Zi)k9B3zD8dBSy@6ZHh_tET{78kIcP8G2ufMdmib{H1#l@S05u(52X z!@Hak5KI2ij`X2EP)~}DU($Uq7?*I|X69%R_ z|82nYz%yQlDnPsZ<@;#6M%#yeF~FbxbUO^Ik9_p`%D<=&3V+9q5dL%RL1CTrAqwoqk5wt_GnEq>_a+`yI;^{5AU-9MZ@zupwoRi=k6E^4RBo7{tlr* zO)d$=WxH2lXVI*qZP6G#MXt#Rw*Zey0ja5j^sd*x`c_Z|Y$!4<;gC?7DemmKn-+Me z{gT+;Z>z349fRN|$^a1b^u)P2CC#Y-G-nu$Dxpu4-ml5MOn)x&ij=^D#cq_yu^lt^ zZ(bis86j*&PlsGC0re1j>Z3+?9Q$w>vkatCA}Rs_y{Dn@!&J>HIrgsfzW@1LPXEli z?#zZF#~n>Z$Sbfl$Z79552Y9G$0W9fZnJvuZs<2xX_a(Yft z3_uOdt6uR!^#D>{a7_V{#3T6>?uxvCJ8bU*I|V8AM}b5~XZA`v0~hmBp1M;$hR)9- z_$cR^mI_c)9rBsZE`uP9*Zp-7#48!cM#5f_#-KlO*6b1F{oh>+r(H^|W$z8Kk#Tdf z1dC3_;{YtOO4)&ucsqe;1QX)eQsC(0rKNz0?m_-HwFZ1AOd=fmPs7*CI7434JiY%R zx(?y!*=?za6KDUp0+Yx;#ux*n+{)}AbuCPCfFCXoajl{cVngl_ed(-S2nJJ+prI+0q%Xpxm8i?oHhDOq z*s)NoiH1{2WE}X1NkdhFuI3hwuxB}G^alNWZOzxyV1G&u|DB$j3}wW&ps?og&B=+I zPji`3bgnlfhXS>*VTFLA|GW|Pi}&mj7><3T$f>8|#;*+FT#4`=3pcjkiQdji>x9xS z2_TyhU|5g6w7u#|Q0&UZc7lx({{hlz5$2om0}lUb0jL{E7!d;0uhBb0@ecqKMHz${ z`+VQ4IQ>7~PzOGGI#pwT%_X(_ZP5I0)u7ESWZxo1?feAEjX(URvtmi#0}nGrt$rkZ*T822Zq1Up;k9+9x-w15j6gPLaRF#G2`Fx zbe?57+jMLwSETL*u?Wy`9W?d-?URr<|InL*0jLQ4bZOrPD}5o35hX&c_V_m&1Th(t znfI)O-f%$30a1d}wQHfWZ5c56i+cdk-7ABNcPI_e@2GRwV@#=99&Ciq_N6K4>gHpxE zB@tpQXP-ed;ra^VJ$tXL0%0SXPYf-mtN@h}Mza#e?!o@~h1?t_!bP3O>>d#eMaj?m zIQoZw&)T-PRw7?z@VT;<);_nwYn-i;@bJuVvFve|A~l*h@#j$~uobsV;RZ|)B_7s}eh>S0&DCx!3m5{Miq zj;FL&MZSDC{1C>7Dx#L6S!b(*Q^-`(jRo$(vD56;{A|ftC9`9nzZ^n-eJSJu{I}?| zvgLJ!Jt#+z1%sQbGd!GJF5s0s`fF1k3d5A?YR)wq_;OA9(0Z6%lx6z*%rnsi6(0`% zA#AeLCYlKT{p`-Nga~^jTNieSxX9Ar5x@l&TEC(T|!MS6Xo4_*cAvg~)ny`cCag)r}Z@4J; zj4QDZ*bCoBne`hzV>|5CUR5Gr<$|9v8y3&TI~ zoY~g`)x4O-vd)6{Q6u*Iz3pPn@u-$!eK}#wLTxoBDCgT!eaYegEh=uOI24<2V5f@6 zjPBSS^J1XwO)vd-qcz_r;2BIb(V8OTbw64k^+9sSu&|r%$OgS9f7PU|RZP)a#Z5Gh zY`Z6I5lf&au3weFxw};~A4GhwJmEft&6(7evO_q#|GuZo(WslbPyI*kY9V{v3$HzA zQI4&Shm-w0l1Do>Z~xlcDuuE*F|E7;m1MnTx6AhC0mhl#~X=k1F$c7E@ksHY? zcdtf4@s_R`DrENQa>Fz zd@zvs3f&2PK(`nd>-9Fmx(Bw`FJ6-qQF|#zcNLu)eZ*#)kJvV6WCf>RyR}>t50%ajE&3@~loY%=w1e-rcErPd(E(pD0 z77c2F4lzISj{K0AhF3em^r}!JGMtI7_O42XIa&pzMC0PrvpGEUnF#>Ds7?r0&Mk&W@inO*%iaCj6L+g3;_xt`vNKSf|S%)TqN!v?!t^exfV)CY9^BN=YEyRd>^n`3-w*6HDt zY1(D1+|wId+s*EfJyJD&rKFFh_i0FfIZsYc2@?NNqZI3mleu!P0hec~nT>?n~Iar2twBNJ@o6;^+P%NDZf zH}c;*rm)>t=+q%e#>$256qE|6;zm8QL;Sn=qRyBAnqJlDE zm3=$dU88mLB?zA4aPLrClr2$;CcMwe(4wruAAeHEQWtln>)1O*@{|%nEVe5t&U00+ zg?f{#1Fz?=)J^&E+$|njTP}|G_9J?|4sXU?MT$R2Mv?`Aceqy6Hj87NVxqN)3#p2Oy`?vZSb+SJ#A12|xIHMs^cx~5O} zwwdO{46VmVO@CTZ;2l=ln4U8l_NYYL+2HT?5ZPjV6E4U7Ft-pi@>u9Pwo?pPHTpge z`ojz@q(eic@PL`8P81G!g%5IB%|pXMP}iH!Ji|4K1SQu3DW%%ju-U}~C^^;zB+I!C zk&@8$4W`@Yq(B)^y#pH)*5-%XY)F~P<*%xrsIPQvq{@Z#F<@+q)o~SXn<#SzQ#LUz z)VjX8umB}Sx4bMUfBq2g9}BYLoJ+JGJC~R8lwFSb{9)_0Lv9o?K`CIi?TzUY92(8V z=WIinhy}mkWX)_Di@&gM#ePHi*=$x?mAs&t@5N zxc9}CHp0tz{dn4)fzHuRMeRN@I)U%Ww8M*MWG;;(Rdv_YuV4dCJX*WtKg9#3?7l>~ zs&dMjb8)sRv}IhcZQZh?Eb?o`_gt`C3m#gS@FRa>81ARs>#9`5+q%^z71|c8taZDW z4FC|aUo?o;fDkkFt0rtUGv0nM1)Pzm@wO@`E}p#V%x+c3EkLs(uhX+vAO*1g2hP*T zRA9F4KFb&AZc`ftqr2CNExnRP8YAfKY|me6cEF!Ir8#H^IL(u^iwu+9_L|k?qyS5t z$8i5pN)yW*DbUF&Cka1o#QjO~Q?tnEjL!5qQSMV}v%0omxS14NDY2z=&2DF)_`VPfb>|Rw?^j;a~kf3BR z8C^EmBE#c-gx(x5XJf<5MgH?ifpcr_cLF}PW+d$GHo273Lp;aSHtI_mZeDD6a`Z5L zdsT@jQ$4u&b-m*F>@&xv7fFptD|c_K&p%&$>p7%7j>a@acb0iAwDb;B5O$AsVzbjd zFb|oHSoNuA4cU@zh;#}{zyMqRpITEYeMzxn@Cv<-;uhy@PB&;M1xi{Hc=Tb_g z2Pv9KBoEox%>YzGY%j_mW@UIiK|517bGlo~JdfudX(f?N_UI$jZ?9=5dCwUT%+j_t zR;I$YS6i1tFK_4bBojYlD-82oRu`wQOZmwvRLqCs`ySPo#zOQ|4gqnP( z*um@-p7n=StG}ze^d!PFhjPvSY(C-+Od*Kp`pvK8j8bQ#wWQLn?5h#|BXx~WphBE6Qx5u9K~{@5v$E{*W7iHi;L)ty2f-s_7nA%}<@gHToDE}~d9 zSTtLx$Z|jGK5v9mM$1OutrnLf#8H36+2tXuvE6saRdUG?#e4Cd2S%_b?sAp(jQheoUDq*WuvM$THczt zG0U-&KldqYU(B->;d2fTjOQ6zdq?M=Cf-jmi=U&Uw|4roD63mxx#@!x$*+`pnvhoM zty7~s8!|paU+diyK}W2qHGwZP(aqP_5sB?y(kErTALZ8)+H-%Ab}cr1IhQd$k=p{B z*le*WSa?0*@8Uy^UTMYrqwD2l>d^bshT^n!E)yP=%>A$|o{fRPbhJc0Z9rpt)4g?P z@I%^U*@GfoLEMB5igRMPNJn3b)7LivP}5l+6UPrQd0aHGc|0Vn ztZkzn6e<6JjG6s3=-L($hi7k;)(WfJ^|Y1pJY;hyqob57ht>vyhrO5JHtCM)wdy5~ zq}4GWqo3W=o;kTO5C-IyRCwcuxBdMjWn|s}g+^ql_86M=Uo_QL!&y+u2u!P%pxwf% z0IjNlGqbgIxoTBmGhl(;ZmbMK@nYP^0pHoYbe_ek@ZXUyk=?SbQcy1RvRsAd?qGGS z6Iu4UrKIO$7Os1b3x+;Y?c5grO0tGFKj@RAAOz5`+|H`nZmu7Ley8)60ZS>PU3vc9 z1}3Jaoeg@nOVN3XeXQ+JBpg7DMDD`&81=OEd_5dEY|4j8+WyV<(c}zSi6TYWx(*yt z(~82NCqI(=D#u@$4C7Duso$`0c63fvfKe zhso*XII!2bBj|`uuZCfm{`u}|FRgsMdlQX@0qrawUk_K-S7CMeFg};Z>lWU1F)O%RRraId`TA9!-VoA#!4dF>g_Wm4BiPtjbeB z94udqstG>W8MGbjH`m26SL)tGoU7bm8T4D>vOoJ;&?u{~+GYKH{w#4p-biUfk4JYu zy@{ELj$*9A=?g0dAt!kE4zeJ+UvfTBoRQOIi;dU{u98tTc@(gkR~wU^d|>FRzDG)B8+JGx*f)wyrwbnOwE zUgjpe9xgRR&aUJjTIcj@=MJQA={X#1Az0g*TaZQK0Ly5(bjs5Rk`m?Hxtln&0O>%o zwOCl5d?xHsOhH52L`ipJlk*J z`JhO*NND?Toz^8ky62GopoM$1vbycQjH!8>e@3&0@5tdgw?!(UFx~L_9tP1pZ8>l?J+nfEW6?>Ag?<{L=;` zS`{%g*iZyg1*GF`hgl37;B=TAmBYz-T}Zyp%W|uBi|7*wxpBl{=!hcYqF$JGKVaj< z%DbK{3~rg2D+wC!>!w*NWv!hp58=1;i^jj@`{QMq4G4x&i|GhInh#VAd_kS6r|`70 z?MD$W5#I}iz5o1k)e5S$(woT$H(~9X8&{=)`*_V<$0;Y1u5`wOU@+_gGhAC_rf>>+ zBeLgi@A?E-0d{c*v$b;6?*YJ}3Q6yP*mV}nacL3T5xkrxEh3aT$Aka@F4Oa zVe92Re$W#9!B?k0D4k(8+GW)nGYxLu7yyUbPD>1OotreZeyI*Bo62DeDsSqOG&2m! z&SCR=ZX4-4i!>HF+6*eBH>rGEU12&Dafhs^>4l_UfgegU(UA_*G+@aNl*FkzZMotI}gPBGHqynMNWAO{(BDq2c`b1@6` zy|^r;&;C%-!8;Z6d4ATotW_L(r_?mzC6E%X)jL-Z6$$Eh%x#7;SSXq|4s`4;j~aEF zV^|#Cc$w{F>*AaN?8&jcK`iJYb@p57KLW!}K(k25C;*Fq{aTj*wiERQN`>G-?EB!r zsFt7XFBtDlg!8i>c^ii+UwzBF)3Ib*XajMW9+z6XXbD<;Tq7%gV$^XUGHApcHFnPZ z<(E%Knxrc?elQ-wqkf*DuF}38U=etb-ILMg9HCx6kQ}9bs+;)nszSO$MqYQn^SvYs zN&lRQ?0S7iu@|%th-n2o6!3l8U0}S$E;hkB(@(NjP15F^{NE4m?#V(ocozfkpkcx@(~)Gp_;%4aU+AB(n&W)Wcuf{g8qc2JK|2TCnHdL6E+t!44} zO)J%1UbC4tUf=b*3n>Vg|BIVm-7D9o0B5GA<2s?v9snP9em@C<8V;<~o5vR0%n8?g zba7`BN*iw)t9{sJUx6yAAhhZG#3-~)Z&28YxIE5ov$ZGasd>G?T*_u|>+LGv?@&Lo zpY`vQ=oA}zJW>$*rz$QM+GUA3=f1p$XBo>SJdHlIKHaX=34hDJEVqc1_S=gmTeVmFd02UKi>|{Jd1SOvbvVCMGSGN z|B!R;R=1;(M|Yyp)Q0o6!Jr>GTpf4Rfu9L(r#sAG7Uliuu-lp{q^Nh} zZ7>}{1D;6X(cK-6x#rqCxa0&5YO>A15Jx<;=c;QxKmHE%7Mci+$$NanBAt#)?R}aF zSZ^RH7CwqY`0uOyg|Fh7vc^r!eli|mtf@=tw zUgInTW}gi@glTAc!OR{Bb#3hk3Nv>dTr&5a9Vbm|ORo*Z1*$y0c9{+ZSU#f4Ii1z~ z0qIoAE+!fs4S~sfVSwilV3w`f$dAT%2wc=3^5qgK;Ae4yjBTBBsereLEZgLDdrUB5 zbYnKSP)k&Mapt1jAXJiw(+6Y`9#xqsLFj-gw@Y8T4?{edY`xmEb6FR-iw}S*VP0OgE+fU@!AA#O$=}6a-Ze9i9* zGy&0qoBZ*)R!|bKYWMNjvqk|J##HZt)dNtB$DTe}%14AyVFmD5dy#ho*Up+VVrfjX z$e)`+E@Q(6$H8jkMA_#U;L9D{98VY1pmt1}+Is*A)-tw3x5uUcdx(C$=$rfJ!$?*H zdUozLoS7){J^#rT%g%o1yGdxfe6P>0HmKm7nmyj^Kjom30)yw=!9l$&Wd|NqT~k1) z>L(04+ylC&)7`SC5H63_Nb{Io!Y}9wG#iE6onTVHCIGmMOI4T>81(%)Smw46R;b9z zTRPDsssS-Lg4)Dilxu_TZ_2+eZe$b=al=nIFJ;rkIP92p>N!xpaU>3S&VG?{Bc4)X zxaW+`iW+Wu77FPjc>k|JVNx`4gB6#$RqDWOwA<>Xdb1CN#cqz;5R@X!_Q$wLbTk1v z0Hc|?CdC9yxb~ZWqd|@SUAt&^KR-LUot!fh$vOAPiCraVRa^WQC@4%d{ZF8v|8A+Q z75vBGQP1Sqz`E0;eti-*M=XTc8NYvHHE@Zqwu<17 z7iH0o-!==4Zu>OA+~+rF;CpA}0L<7l*{JF=gF7KkWM9qxBhZgi5pbheX!3{F%@@yh zZi^<3p^ZWM&aMt|16_^KPLV$LOW7S#rSI??%c;P7U&oqdJ%0GVR=2eKAc%fpz0nt2 zu8KQrs(1t9pW1Vl3a5cI1Lnj$;O>E+_B-UqZoASUj^RYlAAu|q>vC<`u$_6S4}RDm zTW+H3@_kNtV;CCmp?^HAw#1#)^Zf*rNwCu!U;Trp2J$x?n{*nzfNJWxZ4~9Tfaupy z8r`mxQn~AJYO+0~Kl@9@2V0pgSO6h02QYi&Vs`A%bKwd#1Dtw5d~lIG+!T{iqw&go|!%mwXc64F_MBx5K;LZd@nF$ z<2s^sh&eCAIoz`C&i)IEt(a*&cm-k{Dr^4L#Iignupn(0AG84Dr@p`n6}r4A%taOb z(U2XY>ghQ+o46>@43t}a?uTnwgbNwC)UwuqjcZ+G{Qf7w0&C$c0^eVgeDPFaArJ}Q zF^^ZO$JddZqeh;3ehk56sg}Qwnr&pQZ>Om}`$CZy^I8DvYcZ0rWKZ`MT4_OPJH$`_ z9_H8ur+Pv6n6V*1ob1**J1uUhr9OMlSu#V#n;s&l_*SY1oKAMAF(gF*M6%ysbA^ue zD6ZgDVCZ0U2V!O_@BBDc)_VO~;Qx9=gQOA5O40_zY|i;n`|3-Q1Qd{(^9M)i&4u*= z4Okc<$$sds*l9${yEi85I(F_ra_#%c&+ae~sxa#Qk#+O?u*DP(1(YyUeqs0KwSx#4 z;Ud8-2?JTkt~Uh@bsxZJ4lc>HnbUf_v@sR{N9g6PIexlT9974$!(1PHE?zEn{WDx^ z`C0&R`Vy9kf)JdGLBt0JJ$ix~6MeV<{V({GFEgc@gKz*#CAH{<^iz@_h?n;&=pY@6 zBjg|1lYIDyhmvbKAz8jwMT?1^K*TSRnc@3lBZy6F9|ot zR(Rc0J}xFjHqgdhJx8k+LblzvPcXF=j)YyUIjl7Bzyj`66k9l&4cHFiPbSg^_hM!u z51_2fs6Oh&L=yziJ`h3?el(U<&UHzo5t#|JRuPO4%gGnloI##(3!c#d4W;b831jIU z>UY{jZ}1}Rup_ABd3fWy$d%V>k9RI$K&$Tez+aOS!8GR6aRtLkMb|>F)4^8|Znqs8 zWQ#pE!eaIP?{_msTQK;BiKwuPjm(0=Hi{MEhMMFvU136dXwwoZ9Gl?W)y2n7@0zrs z^{`6KAt?=m4^HMU6IET&M6m;~2)0Wt_52ziMz;so)qBT18~Vd@t!d{B(u0b6Zq@R2ePChXA9HQ_Khjg&qyJD0%-%~F?nE&hJUx_~6 zXgxN}@?asrg?0VaNhDT%$*+7lWc51M!X9Y+kb}0q zR5Vm6UK@VU!tQN#Sl9qO*4<|!)7KzstYN2a^^~)HHqmj8 zW4x~{F^*tfRtysmyUHXroPNSOJmr}TmW^Fg$J?c6RC3=hzR_jX5;hL^>D}f~&5EUV zYgLOXb(5|F%lf6}A=?~s^MqK(L^c>H8rfg9-nFR8o&2#s-|V?;+X@6z(y?hDBV*Ay zT~p^7#1g5~{LiCz8W9n6;$kDD$S;5Aw?L#-_z7#$fw>wr)8QaRa4kRYz1rpmiW@ab zW$K@v$A(G2`U8pa0%Fg5a{=mu?B)zc#sv(evgJp*N;phF5d*oEd@3MCd`@U2l^(?| z6*fh?d-ex0d@?S4^KDqgJu{WI?ocVSY^ll-=gMu*$LBV;)5Z<9$io4~qE#MO;F`!h z-)@7lm0ZG*^KYbUvism=xb4o9slg=P*=3~_X!b6B!ZaHt|n&8;>M(fKw>!S-1W@%*- zEKlTPNn^%Sk-@UVq#cdquL3ci%Ib0+cX&v>ip~@4bpBfz2<%hU7#6Gq-E+pi=N&N{ zlmXga@OIGjtCx|0v6uuvU?N$a54NZVjgKKu4E&I2@97af@A%{PH$9V=ph+lHG@X%AhE{R~= zR|`3bBc%2=Ha#OFgi>hn`c?VY3mS4GtngFT9Ut^m1FP5E*VuhtTi@xh^7+G_AeEon zBo+pH-YGQDZfFp4pCY^*-9btn>@WK{K*Q=-cm`*-DGOF2W5l`|>d|@QIa za_pXiSj}XuNpZ8q>k7*c#cy<8pPhOk^vg3XLD0|_JR<*YKS=42)=i3+bhVY!=Te6Z zH3239bgb7I_-VVMi4)tkn>?+;8KtAe8D5jglhCEwz|oB4xD=p*OStN9E4i>K(=vly zXm79AC6)dDAT;rK__6t?ftR)jrc;!06Bgmwkr$yWsBK!>%Sh+-ynAVyI$2^O1K9_2 z0`B~+6q_gCU)MYmJ6OO`WB?E$1(gSZu|IYZIREyJlT?z_T24kZOy_14=8`tLx{Sn$ zF?Fv=O7HtSHn)`5z1m3eEwMuQXo3rDM&>5KT5z3&zMT-9Q~h%I8w6oU_cHyPUzWS8 z%!VijmU$iapzyLQuc&gk6}Xh0PmGtKY{KM-=1pNzfRW)XExrA*Dnk z8H4*2v8m6r`w$!k)lZu<3!vjeWL!L`*vBdty_ipbnjRW&`c&Pg% z!n~=p8(7N72YY8I&Mo>c)yXa-Hp7U+q!Av3-#Z)|tZ+{sx`gOrGalaw=4qRGr*beC zVVOvt{c}Td5h(&9?%IcxFGp^>B5Wi+5b(9K*kuH>fIW6ia> zTbtVhg#W>;s{7gk?99r1eAVwk{+8hSg^>r%|Cm&x4Dsd2vK7pQL(D_&4L693JYJ;d zBjO+{fRjX+h!;SLz+zT%dG|O?FRLzWem>DcBrUQfvG4LdJu^FGF2W;&>~!4&5$~|x z%x0v>5MDUcqtsw{y&`jnNO@mQK~Pqf<&y@TJEVyllQI8;QvLt-cx1*vSa_LwxoI$8 zac<2neyQ!c-hX_uO8dRsH9f4L3Ota_SY;SUAXj; z)rZ?#EnB^hFT4I)$?$lMo|*~X8h>o;vEvufX`OEA;BaMgZAI$c>cT*3T^&6%O^|V2 zPh4vD1o||}xd=R1uOWn^&T%x4aM=bMYHDd}R|9fY7WVEkF#^=t%tjX)n7N*jU1bvm zS%1I^6x5)4zfQP|$hZ6*eDZEd<6xh*GH7d?ToCj3*Y>R1f;axaupJeY0zm_CIpZe1&NN;rE_BheipE28_!~qzKrMgnhb)#3 zFI}t^R~~o21f!)dq?a7s7RHv3NE}^mz_ohMvV^Z#BRNGw5}Tlu@39(I;99nm``61D ziKQ%@b2*<4}TRkGGEH4ocNJ&y5S>2dVFmwsGR$G zd-JnMfw&>=QcG9MPN)BYUA`O<+HYIT!s-%SH4wVY<;%?=YA3klb%qfH<5UUK5-hUK zm>FW~cPi47THWEm9Vw|k+kMXl(qPM{H`U-9oeg%z(N8A)#RepuyT$p&%&V29RFa88y`FUBWmFRKW5@L zqFXhnS1wSL8drtXpf}3N&Dih(lvasVR@lN*1{PnL;Kx89P)1+Y<0q@aDYe%sEZ2;z z7}tRou!b!5w~SIa<03vFIiUS1l~JzQz?yJIo*`#mfyI68P`CO_ z9b#M?3dWE{$NeG)lt&nin8i6Rsu?ONKqv;UdnB9#%tqmAKhld1)*sRxFsSl$a$Z}m zl=@W|(mf%wqQ4qW^v8#ZRPOJAqH2buzl&Fw+6i>m%2$w|tbP*fZ8Ngu-8sFHT#T+R zpy3jsFd&wG$_1ps_{}4WoV0|bfEENPs%q2$Dinwws#}!2^v94!7>YYyV0?8I*wPkQ z9h3`&L{!lGILIjZSN0g)Sc{6;#OHRvTlH)Zo%B!Y-$EeTCH$$}H*W?6Kvp+Els3z& zN{SwdzPH}2xN~}*?m==<${@hNZ^-IuH1q!|w|Mu*-H?z2So%Gyysb~@7=6)0(CE-i z7lhBi_af)X=bowdP~2g)*O~B5)_VOfsiDk~hKuLlJI$E709@ZD8Zs;ZO`qfqVD1&< z`VQ8{wg?hyqWNk2o6yQZaC8N4EU@Q?Cb=#gOcJl~dXEIMd&uaILcf7Tg-pLN^N*nf ztUR=hls6E*9jtthB&iUvaLsfO;b?wd>0XOfM@;2IU<05f;}jZ^4@yn+01AZiI2&jb zLUoaUVMVI71)#&M^E&gigvU_r6JN==2FNYE;+WvHd<&Ej?PI%f;|_GHEa#%^Y^~t4 zp~=}VRVNpti;oOwI@>^(8s6u?*`HJ{lEjp-1Ga0K%<MaEx0onbMHXW4fZ$!9<|t zlCuz6eNrza`Yo`a3i?w0PmPf3$zNoUro2{nrW0CfpEN7l=3FfQQdi&szpOod4$dRk zceT+myl8`&r?f&S4=sQjG+7$D`Wi(=C&a_F>sOKUsb3A&?k_}-;;kb?ETRsdLV9#v z>tPp~my3|8u3SAM*m$<6k=#b3=5r0js#2qZo-gFMWEDS?0$`uro4Lo~lUqmtTe5gP+B z63lskxnw4K2jV8_Tg5&V-_C#`O83FE1Yj>#px&#ko3+&nI`6%qRBCfc!q3grg%t)V zEX2KM(k2>voh}$NgJi(=`-@jlwRsp`{!#YrV5D|ItiPRHt+9({{9xe;LSiyWy*Xed&t zK$aaC-E9fI8z>a!-($7I1^{(fCmQkqezV_m1>ieCtWCc?PPPx+gkr9}bh$_nsC8-} zEK(V2zI(I2)_|Dg-!Mx)Gg+oqN4SEHo!El4eGeYf=hRG#utAhxTR02&x@pAMnLx>y z(mS|Uji5%y=NZMil-~2nD^{qwZK458es|s&fIjn~Q{bGX$HCJfOPY0?nZ_vs#a;J? zd7+`f8N3CWg3&7|ck)Y&LO()!Q7&NO042|IG5EKd^iR?u2)mD|FZ2K#oK-qsQPTMi znUiN(LL+m?gE>%Yr3K2@gNIUjfz}ump`e^>`0RCVmSlLODZ48vRTD zlj>&=HueW#>9cr*LSK#LJ6LRw5Ffs7cj#*j&Q)+@?g9(pq6b{4@{P~YD5ZaaLg0o2 zmqV*p(6jf5CiMZd%PqInC(uF1sTzWcG-UFH(6WCo-HbF;wm$jwLVLexHMcyDa#HRe zNC8RI#(BdhO5qT*_{wTZSr_a#**cH{GvVMCKqhJ3fYs~(j2P%zi1W!zrHM(q+JU%O zh{I7#!KQfd>nM{PfbtP819xI!E(``O-Zs(}w`j<7OWr*jzT?D3?S%F*^?=wA3E~q!_FTUL?i-^KGW5-7-%?jRam&?Pm-MGyfPY1*EmjB-rJ2}&nmh>i z28P_j+$SWnJJ~8x_G+!~wUk_KXr+5h1bd2Z)wW+* zDQI)|x%{%aAR-cMQ&pmb7zHde!XLX2yj}pUUPc$30^sXA5~*lHpz9z($Qgo+|2F2? z$=+Ig2cm95(X3Wf^yGG@3++izDEegn`)K<}=^y$IGpd))Zlg0q9z{6>3Pyu|a@l(H z?u7w%V9})~6+K!HBVT;-qQ~Wp6_0;989A?fG}H-LWuG=N0sR3v)_VRgusC*TBxdd4 zNYJn3+*i1SSp1~;O6c0wbM#bg1>Xr3>issL(2{iDoN%2U86thLEt-WHP7I^F_m{gm zg4&NxRq{=V5zfhagI;F&uN|ScKA#`6nbY&(G$R+3M`_o)XxW8z{v5lCqM!JuD+#>9 z-;XUtZp)v2+6(=^Z7W;A%dalm$CnTcf<(H& z%+o5YgG3egyg%%H;b}d_8$RHKpnLaj!5Otx>g8#~L|*=Y2n~YxXYa=taS4~A4=cr8 zjTlNwT^&3#Fl{)#)!#6ZMiw||QPnw*4~rAL{Jj%Ni{H1HrJVk7I}qd*soi!Fd>%38 z8cjl_Z0w&SFWtgOrNnq97HR1D~^Bqnv(@l;=QU)eE zvV7u2i6oGCs=o$ha0yk@P+Enm(>b{oqyJa7MOcYLu8R?d3((RsfOsk}sp=tD9L%j$ z`uvRz>Ags!bb=gQ{TTL4%qLx1K>R#MNgaM~=@f&B+oyn>JIqfKvQ9$@9#ZJ0uMf>P zM8i2CZtwduro?M`_AVU^lY`h8N1-~h#El>8B4<~Gt+Y-`2e|$Hyc-Ooj*J~Q-dyu8 z`1=`Hsqz;a_As?{oZ1Af`7d=@`j@&;cAa>hw1dI$ONq|@8r8KwL ztKY(Lv>T?u)O1asf17QHkk|ZFS0h#`WC&qwurD~P^v(fn^L;jS80TwyV;E}DYr_a? zgU9RQ+;47M=8NCGTj)Zr7zSejb9<2(5y8_j8B5HU%3lA1PVTUodSB?@Ie#7mB1}5n zb0vNFJ8%m=PrNyow!02^Z^g6MkshpcE+hA#A?C^|WEWiNs=dCY24LuKD4iKzB!1ak zT}>Um^YA|{K*K_3SrO^hkV_vo;`kcfB+v%Phu80MHE}~oSm3{Kg8jZm$g~s}{bg~3 zX486lobWj4yNVU)-pErPmVaP+JNW~PE1iN)zCH)G;&|UDaedBIxPmJ+POeF{I-Y@# zse_jmeURm@(N4S`BClaqvAM2nLwRMOvf!P4Ue98Tk73;ZF89Eh6%7Ll-!_XBEZt+UcGpPNBe=ro6dM}Azv!q!Xl!b2xg8u3DvgW{%C^3o@$r%_T>$V2mW(ng)QVLOehFfnb;awPoEU z(En>sWK^yJ?9&^HZ1Y9hmBb$Y+918aNT|#Q2J+`htiC}7GdhxIHz5)FDrf44gH~`J zq)VtGKB&G=rrg|=<_PzM7$pCKB)0K>rMMv{7}oCeoAb_b>X30hTN;Xj{KEheNKx6} z@#LID^;&2S2$Xm&$#ME#eW(DO+W*7trOP>y+sH2?)N*znA{0@XfT)ToYym6?gn=$M zoIlcr!&v+5be{8HF(whz0Yt^%+Doy+ zYmJS~mUr(?J;~3~I~~392wI43agvlrJeMC~aN`n!VfF4~bxF(1IsPk)!Ctp@j2_wh zkQl(=7cb~cIomB)^XNSYpke~)3j%_CjfOmYcfw5;ou>)(t;ho{L&EWgl;gT^85cbf zJ&B#X|GRE85l<96=46Rc+Jm{nYfEj~;8ViF5ovhtK~q1~)0({xdY;KhT&$QetZ->` zcli@&T0EnhGsDQ_#@zeB+*9$&y}i8jZ=T`xHS#;B)6+e)9%yR~=VS|>YuS19_ig8N z$~69dcVq<8{ejTvnH>{E_}X}>W%E*tZ>{rctiZb%zkU0&`Lfe|4mG7{M^3yBg7Lmi zS9Rq{Td}0X7`MOQ&{JAHF|CcWTc3j)CL;JT3myv|%cgP;BkXJX-4mP-)uSbgZe1e% zsFC|RU@Mc{rEnEX+z^?WEnFhb#(Lf=TZt^|ZYqOCDzE)p!&40kfPL)F?HXR%ef9i9 zXLqzarchV!W;sd-efMBgkeBG~^DV7sar(*oO9&1bi>9)e-o20C1g#qMQkn?;opYZ% zsC?47>bVI}*qL^RRB^ zdsO@}ow)<8R}Zv`=^ejp7r5zQ(`|nO)hYuEgl#DrP97mPVUr`(hcoBK|EdV#zQu#| z(c!vgM-I}#wRAMSVV-d}HGV-DN^haBE}KW=A#jf(`FB17(D2(;WWp+f$()*ruE(Zq zw#1KG>bY?_LtWkzJ-f7&wv_j3bX@Km&`TY=e`alUQoNr^$DSH6dCM@s zjxx-Iz>h2&=si~6=zoj0beMQs`lmBvy06Ng*_;-&DV{yT1vOIIIy(FqF}9=DO|IUzrg(}zN5OV6pdt{xwkBw#^i4ZTVd>icojE=p>=wo=^X zFK+Ut_;733lzi!T53xOA63fv5N@&8%U2J+b;aU&xJEOfzrks2}c3Ed67vOmZ7)~DQ z-y({M25zlL$a&QWOw@N_y;oV6OWtQp2br!NZe~KQn%`$6SXs^BCw?E+IvMWNGPBS* z(9%1Fmytmz;FNH_?<=WWw(STTy5?;(JW3y~bS@F(G zfzrc^Fxz6~D|~HvsW<$2WE?a&Z8uZwO3R9!iq>R)KP1kraV|dHH)7$w^5!t>kU(L2 zg51qKhs9Stn(*Pq2g^d&R8W<6@aiE-cgp@YkhWe87<&!nN_o1$@W#Z9>49KxyLg|Y z3kPbgR*0WlbQYX)6pxP{H9Ot)P@i)$wC-1o=}Unax3QNzL+hziYg;dQhS#l=R74Lc zTY8mbO_^4V_U5&eX$=~U>!&&A4x}|>Khlskegr@8M8CV49MUmZFUid^ludcpb@$1l zjt88vyN_YV{6)Oemy6M-MgwgQkBDSo$6hWdc($%~@BQ7-k&^h3W|PPtv+f3l zW~aiGzuY{Td?)23xU$pZbLoZWCHZ=s&2+oX#5m8mo4Qw5yX(jYSLMm^cc-DCfc05q6oBn$o&`Kdj(<%)N=g8wNC|YJ6+QttHutKQt%ji%}kyiw-=O7*e$G<1Q$TDRwwWie%;K_V*@2s*^2vi(t ztgxV`E1`COe8EbB&7@$$N)uP?)mnb?mET#0-eX~hAE$LrswUB(HZNxL4bu4f3~w4k z$>-7`FDKFMxN!^CF% z>NAF__G+W$*v-DR1rLPBEdR1pv};P14qc~l{++f>NnB$8+aP}1i_v>U-*5;TQEflm zZ1KH2zH1DZ;9!bLH_%lzLE&u+WmC013`b22x(TbPRQ1<_tdcLLC0Cq!eLX`gnguo6 zpi~xLwpla$(RjU;?rmK{r^VN)_C!l)1u-IbI@TH z>4zAtW6Gk;bfp~D_f|PV0C}dt)`{MMis4N{!MO9ejiDPTm!!_xhb6fw zadWlw*KQ=y94W9bA9!k{*K`m}Sxx1Fo$}2~Z!bpCn`jGq-Ug?j6MZvY>m0J;jI>B^ z(B-hISI|nw{{Sy0tGTMz09;YI(doAU2iE<$3!%+}XIF=hLOx6_)ylYI{*4O=g0a&L z+U=6ZG5Bv=G?jg*@|~N=SReV3J1I9(yNq-sxFT$rxATsfC~j4vC4owi(VaceI)0bs z!QJzIPk}^u51+-xII)CFI0@kI*=QMpCM`lVS|32lc3Q==qvw~dy;z*{X~78#?A1&y zNw1hLMyx;Q&WiTaA5%;}Ui?)o(3GdcXW;Wbk@e%dB_Kf za5w;>L+F+lv9uO7xHUhsviUp4@t0J8aa}e`*TU(=&l^`}v9TAgvEGgp7;ODznM7Ms;N;BU3dX zOE>*Eo3{Hd81j3z7xgfPtUDmEgBIUNvgTk+WHzT>4t`DT?n^D@^Zhy%0;qZ&Gmc!w z@49M<-{q^*dooT3>I`SA?^O+8V*-zW0h)AIbFC>r{910mC>IGxdoh{~;HD3Eyz3#R z&2*(~66ZyjD#A6wQjBAJA!y=%TVKQ?O-nqQMO1W)+PwmaTRA{0-s%i~iy?Ih@`g_z z6JQHV_tBqV|5mAI)%7lp*2Lr%*>H?&wWUp6Di5^!Hm#>JbJS15Q!}x^P6bx#ay?Sx zJ%bSx|NHzL)pNyCO|HP_8UUr%p}ZcPc7IKt_Ga+!i8zF!S)BZj(;@3imQ!c4r8Z^P zzmBqQm_H!y)5gxSK_1+Q=hp`gDl<&AbKt40Rs!@O6aDubcV?aFVMQ-aa)J)_@-CPA zA7@|N1xt^^cQ-mx@52o1J$>NOWPh>T{*PQ}Rn#}Q6m~*`+-Si9sF(!F7AI<(rnNB3 z`i-6O5fwwPYVlHkZ5M2`^eAU5+g*U=zL}+RUdY;di=ImEE9)Swtow(hsc|(kaCvS( zHe9Z~zq!C#C@zc`^>F4oq&(&67fwPJYs!LqT6+ zZv^_rX{=&II8P|rP|hWy?yZk+zCo;3PRVC`(K8JU@6_lBD&BO&`=gfNbjs)dy>+Tq!(CQ+${2{o%;*W?*KYk(2kKk2HZ@LCKDQLvprC;@hV<#^CDL_F`%n$G;=Xcu zd4rDh_yAl8d2e4HiQu<{81lp11@eNDofRyoLlTY5H7f32wZ_Hj0&{6j8!BtttPZc{ zhkNDmcV~~5to8<5Tylv<*U?{d-fZK!7{xBy>kwTT*w$=*4y6OcJ@uh_h*Q`a|{sVlYCgL&F`9C*hA|ij|-|+pKcysxP^Y#sh670 zi5$KFl5QZqUis?TwsBlSas_1pD35uIF|0XAubPKiC-;_o1~ggdZNBFR(BwG*jeI3s z^XW?_uxptc+yt@GO4NX|VzCSXc7o{;#TEti7gu9D`1cqXp6)z2YV=+-ioSJZYv24M zDH`8~BPxTZF;bD+CpIm7z3!ZhjaY7n7mHL;EQTS!VM!Bs8^pIaQ#RsOK(ts3#+J#QyHDwuPQhinA&I5;n-*Q0kTr1u3YxC+-V3%{HSli z+Iuz8|2RN@qSHFVveaSNNeY!|N->+a#_~xjdwUO-bpY=T_T9yMOMtI|fvb5pL9PZT zz%K@#TL>G*;{VMjda=tFH9KQn?&wg9@_`f-&S9_Xy=kXc`!Hx?5>omTp|XYT`cz z^OcUkk^IadG%H7!H@@o=9HZp9iz|&4l@LJe4jS=2iom)d5vy@<7l}$xEa08>$|p3q z)}a^Aw^*DQ2;~nrq*5=t*-_=W4DyVZ)*)Z72U94ymridj|jj2>kLyKt#oaQo{jL-WUaR&LUZ zwjd?G4rXbXbDRQy7q$>+7yQpv)1b#WTanq&@{}#xmp-7KclH=Y`B@FKISo^I!T8)@ zqZUY#iw8aHgyIDF0`2J1e_L$r?$egfsdCgyZ$YeSPod!WfNzPCUoc#9;OHKHdx(HM zspP8>#TO1LgWR5pUH7un;*eNj|D3_MrY__|4f3YbcE1EFqd>5MfndMoj!@z*f<066 z!Okq_sCy4KWQQ^Egh2eYRc?O~W$#Q`!fScp{MB#%Lb(W!f{VunoE(q5Y2ggAX!hLodo8Wa_o`cutEmy^fHKA?+o_V)F?l6w#V7OvlR zQyF0DOsOQeg`A}1jcdD3bU{RLBrxaDu3j;HMQKAq66aCTD8^P2q@&l~ozg3}eSIAy z^`9AAzRcw@nbV*K$RQ1iFPq)&8C<%)C7B19KXDosul7Nb(pTYL5!AQh+sRp?;;N@-)*c=8Y zqrTJ01956e!!_`I$rT5Y8)%ihkw43YwTq7{UTS=2Xp%7&wiwwnq#vx^5!_~M2Fonm#f5#*mPb&(NDq!}RS^98{E>FJ zt-!BCG)oZLI0Ww17UL&Pj(nEI{{1>&TU=mLUIG3kr&#(JXq^J{s({H4z2UPh8UClb zAlAsU-2Q|-w$54Bs_F>1MsNPgaR?2=XL3@~I3agIMN;Bi8c1^)2nQs6wgaGMZ>bA| zSRWzxonH_}|?D5tg&y~uI1|mkqQnOzigHsccwSZm2S_j%g zKhswBDJ64O_YfHZipWO3WR85Xu9}fo7v0(0D-O9$IZJYOUgHHsr8tPzu+>aT*+7{|m(KsAxvB3+(*Y0!NxHPUc~ zkyqf^-vp@3i?2uD3<%?dQ2Jfg%|+=}sG4@V+Ujziqfk3N;T)sWN1Bc1lqd^P;kvVt zOrq%1LU9G>0Oh=(8^_2kPXdS+vQ3(E#*!j0+x+FltGMkr%}Xn|TmwH>orQ6Q13~=i z%J8yC{84@hOL`nduP3jQ7#}S*?{^N|qL0u&Yp)A05i6pvo~1Tqb1bGgRd@)jA_jnf zjYEFSaRV$h=@B-x=QTaG6BW9VXwI8Trd#sco;c~V5J5szy?l&fTcSuF2L>_!lC~tE zu&~+fmdV@uscevchnQ&Ov7d*;<2=B^<5@aTyB@Qt2%*b^39DiA)1NJXZgEaNpL-$jk=zB+1;p|uq^un7 z9Rmkp3pR883H^luE4?qp7U22{m?)e2&QI+lUvrFJoE4A|WWYw-MoL`t9*1D`Q(Xwb z(+`s!zDBy#$Es#4X0GcyDQ|WyT#)Z6>GXq=N7Oce`rtxYuHALMJd>tHJC_+H-{~Y( zzBh~Foe%RV_}O^oDEF9<2dj{L7rf zE09au^JaTT@WNqD57;yv6bgJ)W3i}MAn?wbdih7zGr8*RSl|`jh0J`dMeaueJ+k6L zloj9GSAQL&aa}_2!?GZY#$Ku|`Dd=~3BWX8N;`m|H!7@1I7o(W%Ga)d; z_OtrTt6Y~h9b`n7i}l}2lTnFlZiA5h{&@-dv8Aq4U;!nQ!E43ay(L7#;j)B*;F87c z0V*e*v!1s@Os+tRc|tozG@8Xe?ji#sYLq$GeJW0!^A0<89Cp_YfmRj907=xsxx!|`Rm6WV9BkgrB}+9B!uG;4O-u8U^R1~`v5r$z zGUGfy9v05v3;x>V_FLhgJT=Zg=!C86%EM3pX#v`AkA72Yk&6rUAHFZe{ZqcPn=vIL z;sA1=Akq3&p{XOtQ24LV_CQNhV(+=={V3p)hMWy$plb>|`})f3fxjv`K@O3TEz=|0 z-_5%$+>G;{evdn2_@O&drQ<`Sac9d;BNqCeobebIA$5&RO9y*l#}^Ydbk#38>zT*M zBpGjp1y6loQ}o!%hxCc-QXlwh=y>cK^HTa?T9;LQ&xuoUre8KlrLpg^8ZC`-r|R@s zaV$$-M+jl2FC#B#Nu+5m8Ec+@+u7tl@+p$lX2_G8iKc8bYI{=NPB%PFNi>n@e#_YF zHxxcOFHFkp_IY$wyrRU&xNBi+2ActRV@5-s4Y#bPMMI7Es(R@c1=Ab(BQ62n3$7&2 z?VYlXZ?cPvtSY$DrQS8?>Bhc>qgeRw>#+?1*`2$Tzh5dUOCGQ*y8gQQgY2e&@$8T> z6YP(VFd#+(rC>lz2c}7Q+}xbd{>d}4s<8ZdxAgV962vRjA!T#8g29$MZhFn zzpZAlnl}a-H|ea*j#WYy?=GaX_}K!+Oc2skgw&HujozZ8o4iBUxKLhq2@He@Wv#+N zTzc7#7IB%hWrd${&bK2LaEhoQU3(YZRLMN%k=0U*5tkW^*B=@=erWjhQSnT`B5CV8 z>(*P_qLl>nsr@W75wgT%RpVm9A{m6LfY1_RD)?Zh5&wcy7YfZ4Eo@K#7i*!NoE( z3^ohuF?bX^E`guNTb-Abj89BtPsGs+3#Y+E@S^!clFebJqw@vh7uZgNitq4C*Xn@Zf^2aAx!ZkSk3yfCB1ZZNC?Z`KPdWW;Cv-K;r@CiWI!SIhQHM?8jo^QfFq)x zd^7C6O$YqzvKl0KfG1?b-+I z)*lbq6IO5uI>AF}@r#F%?^VcizZHDL3kC{j#{+^#Pj$5!8(esCTMyIDT{8?;0&;rW zXPau*kKff2ywRnj!_HzXi7U}wle%~>3wlWnpL(;IU#8*Z>^%P1BhlcD-DBgkh1;0g zxqJTy^BA~3HDS(=3F6j?Uu?fyY45i5G_W*6&gC2(_sGMv)FIpCEy)d$WaZWku!E;?uoY372?;j_Moh zyRopaHp26R4V$}eu>E9b)o-LrV@Urp?8Q{$APwGmYp&WD>+yQ6tY+8KV|;S4Zey?Ta&(GgSpTjmCTiTe7oebwiZ{J4-CA?j$o%=p-5q7`n#Z4)BuJ#4 zxr|?O!K7kX_&>j9LU9RhFNS>OMY_5f1v?>QFpgd4+iuzzxfr#t^{_Wp^x|CkcNGa! zhThBUI-G#XBB&bP@2{kASCZ3q?~40m9Z4bMXpxahYKLH&8FDd}+_x~meY@$^26+H< zrzDt~THa`BoT{k87_OyQohfQ@HiSPv4sJ*|vq?&HCpf{3^5;t%7d zr9!*pwiIPt_du$<_tXGUdn+Q?~)oU{| zJrt5reXDug6au;nAGC6>Xqg?aaXn&3T%+?DJ(tZ*kaJp_L1RYTmpya_T~{|ayDYu} zkvRQl{TQZwbn&WkBJSbENcZ`{FoC$zrFFIl84=i_1cjWGvFT4}yKm=xhLh7c`7u0? z#}}q5?Y08ZQ=ap;LQhc{=69zE>8!A1c7TFC#`3x9w7WpgJ~ zn4i!3n}D9Ox1Q;eK;Z?tHax|R-G^a=6ozU!S{EK~&m3Tpu79vZEW&zPjIUnFN|4(O zhDKQ>Krk9`jFUDTjn`ixtlb=zq|Rz}_gE^pUYQJlA>r!Buo|zMZu{3@FXQg(Qvr_h z{2cZ3$gU0dNtYcoW}p9%7uOkxf}fqU1!U1Fu|km_(*e4cXY&#+W%ClN@gEG{cZ!R6 zYiSCF!V=58lJ-|k+8y}pTJL6{c+Y!@U8v82vwK`&uJOorPHgvN=^u8lx$mS;HKm&g zXQ$pm%YLK^dF+Q+$(*oV!Rg;Nc8{MP-JTEq5Nq6-gq<9j1{KlGk9Yce19lwcHof~+ zYhy65w7vFc)`Yhs0#m5C%WfJg|aXUqRyrt8O)q$X6LmWh_El zK6KZHu;#t0GS6mJEV<8YoN1ygG}xS5?3u|Q*?wm$=aP?3ZoMP=o!>`n%H&{eKsO*xJk1Yg_7^ z4JV+O@kQIUn`lN;Dz=1bLI&wv1Vuedx#H}W~@L8KLG47r=dT`h7SFO*chF4M0_>_Ztm=3_^pRrW9!oXQl)iYIxplpj;>9TYmt2rJ zS7i?1g_C;vv~yg|6-d%T0rBatx0bFz8AH9jD2y~>az-X(RIK_0o=6z58SjQqZhXyIfuYlr@%Ne=#u`y zK$0JGD8L9Y!*3Ag=75^69KfL4w!hfFabJIOq>-A4!FTw|8k(?5?KaLEo0C(2&I)wD z&vG`+cm82h)R9Y+{Y!~hjpYHdTeSbb4Nf9&u#ZgS8F$VbY|RCLJr-*SI$VR2bp4XJ z2Sq>$m>6ewso)acg^Ga~0i&!?+~Vzc9q4%pH!`T!s&#m?g%21J)q&m{`ku|O{=-f1 zu4Ox4EKu7&v@_qe+F!z0RIKl zdruhEeI6x$fkAWBQoDPs%}I}Oki8izD*}QHOV-QL5KZm=g2gG02VDu24AhIESSTE( zQ&ZK106%8xj~Fy2x{o?J*k!Ibc!MJC4XV!ErTZ6??~!8u0LZDnow|na)F5A0K+0 z@%~H{EKR0sVSj=_j~4oExEU?rba9oj*5W#V$&`PmfQ9MrVIS)jz*If}FHipiagL9i z+W^%`Z(=W*qKD`OpoLy#iFda_?*kgfFydEm7BY2OC(vT0+ywFD7p_WH>9xKlD7pa3 zqJ090FJ0wY!5t1z==V}@?)DKCnsnVkb2bO146 z`V8na1l|WZnd9Wp;w&^!d{+K_to{U?9Q?iPpRerzzHc=)>VK+6#r@R$Gr>8BND87_ zPI5}}ku^;43HttaF3>(0SWAM?;!S9KfJlB;AV3BWv-jVl)I9;+RS@t(L=4C`+Ex6N zOm2Sd1Smn9J-djpPr!nudVw&suP?7tMt@4u#I(^}a-jM>F~CyG&X5vpTXsPTgp`sdri08on+Pmj3z^3@p8H z*JnVl4Z5t`BE#P}fpUZi=hPd?^~iDq;ku;9|2v_yns7ohX|eoW22+pWZ@AdWZYNV@ zhqhhy?Y<&;xg}S+=61gzD$yQY@t?-0X+^o(Z`qC2IlY7{jp-kIbW)hi9+h+8nhVe; z9#Tn2{P!t4OHRKKw`VQDz9{v068r^~sLtw{pwAV6)?CIxlf>Psd6$mW4P-IFSR{X6 zSVa4qlzlS>2?Y*q27mCHOGLO`f?fJRw{@1LeDIMAQOrI=N`57kdcasZ4CRel`=mB# zizwsnsUZT1yilfK=qZ?HbaTK4=$G<66kjg`{{-qOLm_(FuZsNqVtaIYdEc1st3w1U zc$EtS%-64;qW$^?j?C+XCLMr{*X~@0)Sl#LTLDYH=%6A2ce}M>bNz^leV1D zfxf+-(xQ6+*S9#Ch9Cnr?cjRCA0R+FVy7DTbCUNymvgx;mswW{#nm8hC30|4_HZ-k zq{^xOJ>Sw=Z18mmiJ$ULIl0hr92^hYnaDT@f5~(L%St@p(b_f%*Q2M6MmS`qfM%3= zSh5l&k!_=;EVwym1hm*rgd21Bm6VQLF`eI^*oYC>Tb(0`OeUG@w9D@+av<`_i%3%g z#q9N~mY8sOSA*+kF9G)=1XzwcRF|}ynfJyysASOTw`}$ESxRpRgy5G@&Y}zO}-`QH7kQCXW+gA5|YsK zuyG%Tljj#)3;ky=3G~+Ers-mS?9dgk%hoOnVR5U&cD4iU}I}=emAks+T7CvH}7Z?mv|f= z2oGX__Owd7=Tvb&jOLUof4-5uW_Nb}$o>c+ zpYIVtZia*o&^N@B?h6g?I9BJ=Jgv%m^6I(9!=f837F2{&r6EvIX411ojmO?SP|lmh z?#S|Zs5Ff6b12otMvju?J#~-?mWx7|dgl8<_#D;=DZl({KqQD-><^+id3S%ZRk$RA zfCXHSF0T5x0J5p98qw4f1|eee1Rlo;HL4+G^`G8{8a>MtdpO$VVcA;HrRyj({1CO+ zstgCICv3cEBjq6KKy=^WY*-cjNLRZY6fdjgA~%~I+UULR=MlF57guiqR@K%;4Ie=9 zDkY+HC@F&UAth8oT15!~sY7=+h)PKbC|v@AN`ulV-6bI1-QDobqxXLQ_x}6wkv?bd zwdR_0%rVB=+f~lNK^>FSta+mtfON^y+rRBX>kRDnuJ~~afi2y$F2;^t1CIZ_nhM;N zK+i4_>rD&$<0Go7SH@%1t!N>-nWG+8n_pGN4&SW(Ljrdk&PEtoWE=XxDxLRu2;SI% z`Nk$=9P5Wp*lPfN0Y~P4uZWXQFCEQ+4#1DNG-2k0FK#EQ{K-*WW{YNqrOmgjzhaV7 zFDiuUrNPd*oe(Gy(14K3$mXL5ClXWn5tIwitY%HZA#ro09w?(XI#HRH-IaG_du5Oe zipZN*WmXY6K=(J11;X0iyyMwpU|+b0SqN>%F_uGE%=i@o@#K9t)@o0^SNNg%sp51(4Uc#d(_w@yvD{= zGgtopELOQ1{|<2ru$y8bsmWs)ZHr(}(ort7c@pN-iQyym6K;2g4`l4YUmRHL0bDeaH{S_vu!eWP4R&)>4p_(t-I1AR`OsK}WG!3X9 zz1eN403Fw;KkH@U8}DACR4~Z>VvaDbV+*y>Q?@>~HMe6}T$Zt(62f0{$fC`bKoaXi zROG`VY~3YO3)961GZyK=I=k(k1kd&-3W~oq{{*{?4-8qCv}Ad<*j`fYh4XREF!0ZO z@qTj|%rao+y_1dhbibXqxeYnC{0h%tnMx_?~!KS5ut;N|b>tc#h!O#VY6@C7B zwkCFEf#2z@z5``g&i!g~R*@@)8Co&}R%J$dX=~q)&#H4b2y~82y%0(2e=~vl?rs=# zr-RC`@b7E?bC|O{NUKS~ubR>RPI<`|h5~d42*(}OJ5xb}@occ~fhh2s2240wAtohm z&aDc5SF467Wib-O2xnxIU&euZr>c*g_w!ZUUq8!p)UZCL8$ZjgJpaWkFW-JA)NdIc zH2KTbb8D1bv~CUVgUaE?C|Gt!X)-0BwL=TD7B;-FXkUWW*bPj>Be1G51o}lQ5Z)!5 zvm)lW@-$wW=z5nM^V4p5cJ~?rhbOy8C?Ix@_3%nk0DQV1m=q_l|q63RQb7G`&cs;5{Bg$X;)F)ixT6 z40XYthMA-i)^`DNVI*j3rTk>jf~Waps!f3Snm!wZE{x`v4mYXo+9>hE0UWhL^S8Q zXemya0`GKjzACd|zGJz-b4%j1-}3CmI?*NYR*8Wzf@&_{Hb-VyXe|`q+ey<&Z4n(Z zaE}bq8|W5>Ohw;ZdV6-el-Is&@dL+$7pwMn2Mqt~c)KK^nIv_}J}I{lJyL-9A-zT? z{DwOco=_A*NgZiEta7s7f_e0YK$uqgXyTHGOwp*z)3EE8eRpMPPTx;$Mny!b>`c`+ zzd4nK?6m`ea4#%+wJ45eD(?4Q)l9D6Ph6Md!+d2yx`^rGVJs2m@V%`3S+)`I zsfFgtpa|Lzy4Q$_?N`hOg{3yaa|Mt6q0*CbDcysuOg9|yTmSH2U3ASIFNdNbPwu<~ znQ1)sj0J3FgUXL5wSU^lAn>a}WB_?Qa#;qfTWQJ)iuJ3|{hA`+F59>nGYvZ0 zup~?HKkw%cm%r<0b(#-Ed7Elck^j(B8PlpHp+QkVT=F4S@yMcPo#zne#^ zg$rK3)K7S;b`|U)aPD)L*vN$O0EeLc1==3)R@V1j%;IeYdsv#%&-X3L>|l5BP%2Rv zFdjBvDyjF~9s0BFP%H-)dRS^m`R4viOW%CLf&FZToK0QL#<=4(9Y`v<{uh+cTHhZM zNR8k^5{qOZR>i1=slEO4u$}s<15@GM9qyR8xbBDJ2Zd)7q9fJF7^XF58s$ogu7WDUlFaACwppuHz^)VCkqW)@>TPSZkAI8 zeE~-;i;)e>GChOdmP`GcMOu5sR{Vvl+kE81G^~{050p(cR~=-t`b#mrx~gYk*QiRs zzEGE;OsD-O=|9na;jU0NpDJap3Ue0nHCDC!0X z;C(%J4`R73Lx}=SN_bO%nGCZV-=!&C;XFM$4mhX@wk#Zg`Waz&c-+piyS;2Ex_P!A zrEPWWPjDIo`}5Z6MRZ+>UZ<;cm>rdA^Hqu7`S|XdI?q!~QYt#3pYB4ImHWG}XW9FK zblt|YzzZjSGfl; z2{(mlt}3%L@r>rVCVNvMrVHnOxk9^e_O7xlA9bme!c7xF3B;v|h|Qv<_5pV>^!LJc z7G};(`RM{*&w`l`4gDXoP?Lw#-+k5rWw<(*bP#`MRW;)Cvpb(2d`i{*n(TBhEicgV z^H&fh}-^f+tPo zCs`G%$5ky+bg-;V z!y=e6QYEyaOh79_B+52?rm z#Snbfg5!xoOY7qXcHFZnc3Q4$y$)9#1L}VskGTpc3LjrPcUp2zaNT@vV_WbwD~pLZ zAoRn`WH_J4!k7K>`M4Y91s+6rc=B%No*wt_d$7f8j=ot=_FSQ(sWwX}+^6^R^J}8t zm#I%wRk9~QTpW{dTKW1m`MyR!eSVk$MVx{-s6zkMYDR z9dFt8bTpvyN#o?iuLZTvF||yD*Kw9U2F1#%W{p? z;v|w_LSDcn=4shz$H3Y2_K5p=$_neSthuHzLPYBd&0*IrD_gW-odsNpU*OPq>zQxX zr9>?4`*Rm(=$BoCn(RKT@bh?=NhY=aQ?9;G+PQLgk%L2c`*jevHf^b*y&Xs<3Ml~s9PmrCmnMP2(x^5kCScGckU7BS*$ z_B~<)&A`zqF8*jgdcj2QNP1Ut;nS=YBe!SJoH>?o`~hLr z`MjruxR2!!Ul)O`AQgXn@U5yb6jx|;C~vU8I2;WsH-FWP#-6`vNU+H?xYW8eCL1O^ zias5V5aExHwP==2Xy)R`_}<$XJu7X}c}^8;ys5&;Z7xtT$woc6M|JYap^cHd-q;WV zSl3RRFk1YIyX^1L6KvCOYfrE=8#H=9Ee;FgBfBKhxFV6>Ry<9b6ji(jsy>E3UjE{! zd?hSRI13c{5-zVzqYrz}4YN9(T`S2kB!5F?sof6Mg^8@CW9PCX4~yHU zS}1K2d&oE$xk#_|TzYj=V+h(dK*x7w0_<|i<_-KNr4!tIt*1V4xZq#os`Td)4KB&U)UXXGsC#z2n@N*B4a zGF`aK*L%Z^zB!>G`r^9EwuU(3%j$3J>aEu}sxPfDtS5rL2?gOXT%KNyIc7F>392t) z;V)XalWD+heUrtQ*zm>~4YE@LB`(LfJ<)b!{ntGsEAnWQ7_2@7{U9>@OVhKt!b8;r za6)e9U{o8+)3z#^S=}LwZu=!h0_T47DiuPR*e!6s<56et8grl|53lFIDp5`2GTwik-onhdjq95eWjWYkf*AGKOMkNIU za*CsZ9*>yc{Tuf})=w}HgVMIDQTCxV{^IoAPAejqpA@J^&b(_Hr#AVk+_tgWHa_Ol z8{YUVpfZvFnKbHYVE)Z%%x}X*8wR^tzs+1f_$0V!YrhTgYcf)m`=oE~+_E;xf6k6M z=R(v7_M|1|C0+9*Et3GwtARU~G;vgh^e>R^Wli5_>}L^=drR6U=xMp4jW3j@V`(}_aGk=*tI&B1m@KZT>@7~}fsdqyP?c9&v} zuB@b&7>dqjnKD~y2K1R3ddwZNwpPR(M$hB*UzR-K*^kiUiq0*WGkLppy}Nf@lApXz zH(%*P;q~DSG}**C%rs!xx#;7#`RAV4Y7SPsKupATsi7WJIvtIlEv;GFE3f zUgFa)c8SUzkIv#1-y!-U>^>~De7^Fr>qXZu>J5FAX?tTy5E6mgQ`X~|@j_1`aiQ`I{DLcY)|_sNmaHD=)IKSg=j zYYIm{u?j{44estlJf!Oybr_FAT@P)(RUhg-i2BU%SmNfdPq9YgC~-*cf5tpNdyf!( zw#eOEV#aHC&?~Slwd9KGd*@s8B%@8qE3%OAuLT|qI!*Z3%sIyl%fdfORVDY3JTLuU zdp{~`y*lFgGpW&kI6^O!|HuIai=kk4qCm1S^fFJa`ny5Y+-^&wvqh)Y<+ra9_i}fa z%}kxF#gVZm9}!MwCP@Kud?JRth(0QHTm@R%@Q)Bna40oRekEXMJ>x%j=paHlVXu8J zjER?QxE9LXg35ot$ZR0paYN(ri8L`v({HiMmga>G3ysDW9byO*+2H+wbJJut5#zRk zriIlt!sw-UPh~NjGLAgngg1!~*=-o>ZjwR><2n)+^r}qR&S7pGbf`P&jIaA>7SwB9 z6bpN3iax8Ck?61%gfoPZlDp;29DrEBD=L67ejV!dm0%Tq(8OO5Wi~_KUT?gO`MB?l zw{O+d%ggw>{?-trb-dAIs~6$T(g}ukl!Vb!TqE4pFT#y4KYP+$*s;LRg@JDunYTM( zi})~?scYRad)-A=Ey5AW?S{qo45})^(fo|7#?SK+k}l6<=y(ak>V;ARQ?Va?W-Z^u zGeGya&SAEvoZ!Yrv%sEUmrBfm;#mm0yF3%y$0*)gEI{n>(+6Cz^?R`wJxp?v| zRs#yMHL|vL{>ZQu*`Qzs+TNzNU$Y-jT5^yxhCdCm+ikjR4Rs%I-Sr}m>qq5>8=zk$ z&HrTPqG}uOo#C<1KZ^Qcq=I<|MCJ7qFA^674H_FJZXn4LqT|%8gdtC9)<{~Y?;GzG zmb{qEv$I=XY6=Ev3100sTl(oEyfiF0V~S9E9%Uw8D)b0aVL5*gcW_y2+|B6JHiXW8 ziZ??sD_GfdIdGofQbMvp{vC^r-~(rDe9+`(I}U9LBVviuRB8n8WUs;bG@j7 za!9G9e2mp=aiFxOcSjFXtcG5eKA1Rw+X~H>lIN{CW z;Z<92`G)-b;y|nYv+An@jy!W9z%TgLPxHx1L^Z9^Y+^@=FZMt45$}XME<*w9~*j<$}Aa(LqZps8S6uZSN7A(40H1*u!_xI zzHl`?>@8J%V!hxh$wQo$vVPMboGkLLer8HQ6TJ?X+M_%}!jQ(n@xtx}ep;^PFEBK; z@UhQ+H8s;1X%Ox$KxT+8r8A_A1_v@2S$aZh(5j4mIif&7Dj`Sb<^n*PB8F@=j|gIy z6FCKg14HxE`hMA&)tcpV@lB5q4#35zscm?033D%oTqri&R&nwe&vE{A;)wXo%I3qJ zuPL5JJ^snQD?_M=G)`Qck>c;7Vk|M-KcOTg{iIh^jHf_HYg1nS!TUF>!Z)Ept0dRR zZtEEy-ab(YmE350SHZqkOJ0NUQWy&%7k>ABcd^rvKs}YUpT&4_NmJZM5zh|LRj9O?YppEh%2>eY zRB}_%FBlzKrsoryxJK7qk^|}6YUIBc=;b7D8#C)YTKgZ<>#n1kgI_zvrzMTbnS z$O)t6{w=Dhw0T$AKb}*+n)-etN?!R5k-uM@hF8&rg65XBIXfp{0GOw4nZa5M{7j zGrzcK3D--hXWssB$45}w0Ts5?!Y3H)*K{+y`GH5v1MLaMr_pYAhWT>w>dU-tW@w)zVYQ}VZm{!~c% zeV{Rurti8`t($N#Ll@BY5a_Rg)f!QGWj{R+%+&^;1DZEfOkdMQTe ziDEj;VOB$>AN)J&bJ3%sboevrAJA|d7CK6mvLDr>DIu zjhEcF8q)ylO7h<~L@BnaLp86_E#&03FF_|f$<*8S%m`Ccnp@;J5R4GDA&+?;ePanh zL7xjhSNN8u$AW-!uY5%CFDrnnz>vQ6^pNHs30G-r6y!Y!K0i4n-^j|0wGmx31Y-Sn zY{g%W?5iUTK4(>fPzvXdLWNP09mJLF_y`R?JOAEoo%UnQiV5BvJBj~qR4d%Qx`a6~ z$L-l6Z+M3LDlI{Vj;@&*0^Fdr#t=jGy}cL2K1xv59*?JMSFaMP6bCIz-=sMV?L!+`@6adj3=HNP$Gypa&ha~ z$J|77o}KthdY0%6&Nu-HA%O6%tS>efdDH9HWM{xTh;8`d+v<=GI#u9)UkF4aTKX=U z%edK8Uv`ZpPDr2@JyD0A7SD2w=L{bQ)UY zf*2~hi?L{02b%I*y-IC8BP`7A71zc;F}vzdnP+>(9A#@l)_wP5=Ytbes^fMFIAhJQnXVCHByy8`ezlX> z)%vnJ%0n^`HK|ZB<T zT0)~}BNpZSE@&i+S>L{1YXQ$O4Aps4$T%1s1+ToYOZ@>p(&b%ME*M>SL>pH9H$=~fQZT_~Z*BMtGi56@Jnf$^C$ zj8n8tdI#)`;4%KwvC@dG{vT2D#JZac6U(MTg3kZZXHhO&8D`^RDq3`Ry-fQ1gwbT; z{r-!Rjn@dtP@KaXzk4@)hrTWk-M9W`L3<-K{4ei9@6~5#p|7}2&T7C?(DQw-#7|Dx znHlHn(r-EYMq+%s_2iqM>lPj@oMPW4F~jpWqUrCO3m;J8jk@Nkk6b^DAV;Uhk?T&fUlxD2WTy=nuVyjS3fIEr zcPzCGJG-A#NeTCptT9rD=yIvy$}rG!ZE}Sf*d*C9IhvmgP3YA;dbL-H1$`#29Ivze z1p-XKXL{F<#~!-xTbKx$0F}p&Kbm`!HtZi51jLeHE4nrGSD^dTUR--j-{0AK!xIw? zMNKUHnm!nC4&L6tmm58E*mcKFkB*5sxq--xIkv8}si}2}r#_+`-SH{IQ(&a!%9~4# zmrqM4jji`@U#ZqDBn*%$J{@K68d5j4E0<>O6()McmvR1cT3_qar(*kr#W8=_xW@HL2C@4^pG$a=+VBX}7W8t?GC8QX(wD>0msqiC)7q ze>ufauSLehwKHPGofmufA`#HlS!|NtkQSdwb<3v2gvc1?Gc6P)6!@3ck-qAiK9FTH zE_a*!!cB!hRaRXqF2c}F!=mCQ`DlXbVI%>0oWatj;H9(-x8xPR6aCYw?lB>btr6qr zwhzVA_yPty$edNeVToQ{ngAkg;L(l_nw@l2AH&oJ)TXw`!rWXM6-HK z>zt(#GpH`osK0F}y&sW64#nChzT`!F36x9Jq$XxHGz5f!2Y3qHKkBBi`1GRX4PgBM zjRTUPKI-J9*F~={{LQ|oTPlpApIMjLw zP;%?|xoQs!bx&?jRaZJs)njXqlc75fyp@7J(oDWkcT!k>KME5Lda$mGu2uB+!kd5Q zk7R5L*e>GiTQxR#DiNKMvPYbILEHbk4PVAK=RstY1S+3Q<5I;#m>&VojK4f_TG>)Z z*1hu6;kqf#Il}}gi!IC)I)6XXZ-98>@$kx@ZC?5&$QwS_V%Rt0NueCXw>K^im5-;0 z{g{qZ$1+1Gx4xZceu9pkl+W|nUL!If`DDklR* z?B>>QKdLrvQGq3@;z?KWiH%FRUW2o3d)8{z$jux69-$2sIP^os7K-Aidrt9Kcsp6^ZU% z!`a-AKgR-CZZpE02xPH1BMFoamK>(?1|oh*eYsRR;PG``?ysr3mx>_?X zlqszj!P%V!*cQ|uDA2dJ;&ssYTe=yQ|2W2#L5N%{IjbnRjL$t%tVn%8R?1jSdQMVK+rHE)j=faq7XIja;>d?XxXrUTW5qKSeD_JV zZ$o@&a-tE$5dc+ni1->wC~oV3t7g*L3>}8lB&8tvke(8XBI=Fj@882eAw~oY`aoj0 zu+}T$&r{RXMI=yRmbn&+o-8nbY9HLc5|$x#pn6YbEqR^3 zd~g2=-N`XlF$kzU?%%lr#MIj0$qf*LW zqRwWq_X*6;dC`lKD!Q$c-&4*sz>l@ z@o8RcVaeDk2TAR`-3WQ8R7CQbjiEWg0&sBXSDhz&vnyt9AN$8l{+xU1N~3QYN656j zLCB%s`X`QPR>Zx$WvOEGsx;^XtKDPI!!zdGqk%07YIb<}d!GV^U8jIwjmx_;k(R6C zK*JgFtjH2gH`3Go+ZI3On40eh(n_w_M;K?j$>g)~LP~t}Gdk9T4Hm{-uRE_Eri^w_ zIK=a)+%nGoNp}|4*wLWk?AEx?QS-qJvs~j$>IG(Bu^DsQuV1UQw0b5__82}Ov(kPP z`MC0V+HY7BSv_1lS6IMh+8r$$>@CNBHTGDv;*-a{y=RdAydGZyX~nXT_g?2N!}!nn zHnL3z2cF8GKy>KvMl-jUV3yS*mCJ6@>fVOf?~Re;==lR>`2QtK--EI?8e1i2n{*|I zI{@TBj_5Wt_>+DVkk9^E^x91Y+;pU~oJm?)fNEITJ1RW(?cc%cghAdw&+bP3Qn&z_ z*r{yJLynP%L5+kUSnfJuXr2yNv|5}k+42(gEz-U4xjoFTvElldC0E8wuQ4*SiLrJq zjHIrjDB5u{=pZ3;i^XAS>aSRii|Y@Uovg)&*feK$ZY3m#=u*#B36s0*ZSLpOAUN2! z-5{X!Dp+V~ePrzCd%8v+0@#FEn7Li53*V&Wy1zEQhX?2*9Hp4TvwsK43k_ne&TgRE z_DL>`et<0-6aGoXis$cV=Q~mTd_5^b7Po*JOMIHl=nE)?lhEHA`_KLZ>fKw(&5v?8-knv0;sX+bv2roI012A!ubc~RQ5IwE#P3S~kL5uw-qo(|&7%w`#BaR9JYQ(fw>>hZMfh$n z-a&}K;+R;oh7p+7Hi{aqJD@k*UqW+jLwvxIfh7MoFN#SF3j(m~&=acagurdcw20#m zSv#Nxl|{R#SS`U5PkFmeLxYGgG+fs9MlOtd8+g>$&zM2TH?~V9G+h~NjD7BimCLdG zpxp{)spF|879Ft`TUAJ8>pE5v->-VvSx?G=RguE&V|4d#EUyd2>!IM7p^Jg_ULZx2 zY;*{8C4f~<_Etl3b9Pt5E9Xlps*<7gcL)ezC{YQVWrIq5y{sOjBXLi9v4@=^P@5lN z=8f32-Yp`fdZ2LkHw|X>;&+NTar#Y(lqbpEw}}HTX7riZQHH)Hxq=s`M;W|0+I83T zMLU*y)qM!7n3InmkX6`>MD<@=r8JL$3DJWVKTj==wX@8iEuA*PpD3i!uU2mqAUc{vboqSLzFxzB?lv9lrPO*Z}YaJ z`4Iu;C;Y7noF-Ya#1pPcyI?{x>Xc5-N&pD}$Q#${&1FBa_dGP8=LHJr0}5^PAn!G= zEIh~W9}oe!s3&pugFiFjR@H!6{`<9r`!Pa^P>i9f4pV3)3p|#vUb0ysCOPd!0PO>7 zt4?;ds?m(AfOVZ*qyGcvC_%K7V547LjOZ^P(O(K_hK$~0^`**;w1_Wd^sttC#}fMa zFp7=(FEuNw{e)JwE#_NUbhrnx_ZS0R_VLhJRo-N^D99nK?G;xd+l7=vCB#vIK%T(Y z?^c7@w^kCgt_JVfp0!alW_sMCo)4uO|CG6iL|kzTaQ192YTmjYB7MsDZ7rGMv3Ko~ zj`EV4-cu!5uaJOjmNdM%jJu^F5cwQd34GMjTgc|@_=;C^QE1{>hBYu+* z9Uia$a(rpRo}NO8LuPaxdwso;#uyj5J>V#MNzBI;J6gJahOv{5$(T*8x!{rQER9Nf zvN_d{cp<+Ao#5mL_sIF`RWVFI0bA!m)pqf`yqj%nA!~#w*mH07%hzPIVG5^7-Qe8 z)#O|43Xq|Y{(pvxs(@QkS4rP9?))? zw~G_Nb(8YRmEF^Mzrf9;-tv*{jleH2;e-gxP8kv0N@%*IBTC=?g_0^rgOC>E#lB2` z*?wl4^rrF=Uvoqo=Wv4GqhuS^Z~!^bKpAbROfj~i*%ZVdHU;fIS~?~O;<*qoC~5g6 z5y~h6hLXNlNe)Dot0s*!@Nem6*SHtJROqTf%Z2H3e%4Nx?zN7$YuYXbz>dB?x;=kn zKmW(1^UJTrK_G9*8hTnZt&9FHh&(l4e>zqe{B5sYN|@w70oolglDCP&+Wb-ik{YlD z_(IDR&mFtFDhPc0+JVybIrRW@4-H5HELXA(higa{7KEC##!gj4N=^o57&>W`Y~3DhkMRjq+ro%3)NCz^OLIr)L^uowCsOO2r6ST9NNx8~=zVa4-B7u;hf?CoQPQ zopFv|3}Av{ZnhOp(nGQcOzL$0XWW+@T(OydG-^usOE$NM0w4?A{N+_u72iKbo}9Pw zq_=wCC&s_wAyK6#%#lrVuv|w|Sq#h(8f^EBIlfZ+%CZ=+^L~;|*JIB4P0lKgqtalZ zm%I6TF7#R8duZ(Aifsb|(WzoK9`No5`F90D0bl40d8(OL7qTS(JJUPZ7vM*P;_9D)&p9 zg0{DtE1gF21+$tFQt|14iQ<$yi_MkL29tOJp1o&}`|{MF>%yqM9@021>HA)3d1VW0 zVw({v9R23*{yxza@7&>4e#%ny7c+J)E-r{i3JSdZ&2>O|)jS-oe5mM&qhNXsun>?I zoJ*xQR+k03N{EU^y@u!hAVzSi)f!j_l~$6nlj9Njzs-ALuFCqtP<6)c=-3s*ihl%~ ziHywiOArtm4CFX8y9Zk*`=KjMsmbQT0C0m{IzYr+>R@XBDD{nn0Qg?jC!=}MV^$=g zM*oD+eFTM3&5=cu*}W+@F8@`P!t+_|Jfl_-R^hcH5-#OHy4(crk-nO zo^w~pp%rd71i}EcAa9`Eray0qBG3_`vnQb{r)P_Ci``jd)e8%hnM>(j>GM9VF@TWCeLxNvwKG~OhAELp1!FIqa$AvSHM<@~$LA~plFela zSK}>}o?lA$|7Czbz8k*1bJxJQ<2h?f*+uCFi6YdY8# zur{^6P8Dfncb^q)Nt_VoAzyX_en;N-QM->0vgXqZ=AWFahj=4#}PxT2k2Q= zmY?T6%iWv)P?QZa##Gzu<;HSnkEmu;jrlgT*-ydghPv{|Aq@*{+HxviVd1eGn9g^G zZfGqE*%>mM@64>AStG!0p)GM{f8B{hhZm2hMWy|eUrXRz=V=_)au0T`@O0RHa2URP zDRUVX-bHQqQN4TLPlu(1wYm#~(;ddIh)M6&r}FbW0^XJObEz%Hm(?+}w?+B_xt9no zdsQj+E6>A?UDhZ*3PgHs&Af;$-FU@p`u8Ho$9Yvg0tN2^1DRo(d?^L=T><#uaIx3v z_QzO4mg8}5#xYvYN>A2bpU~UpQkMI@7fuyTFT{0O;>ZYprBP3@k;bA{kbi50M@J2$ zjU6CS;zAwq0CMT7^qP(w9X(fV#|Mg49KYR#OX!ppd@gtjcWAjzo#F=(lnY}ze@-*J z)QdW#k;zPbRM^90d5JT&J+8#9`N?o$RD1dS%8l~!Bl$74GOxjU?gqPI-y&q_F$WQf;b7@fj* z))ISu6;Qldneo;r+n_)>`xKou)DBn4n$J5V=lv5cE#cGuWqn9qD>Wc)ro?C9pSMHJ zG70sE5`6dypOAwlnIMl-1+n*1nNdFv(rgDkU|i9n#f>fM&|g|p515zlyZ!Ii*uWqJ z4{kp$NO$YZYm5O$LAjbcJJ9jXaxoIp{q<6Pq%yVcNe#jvr^+h#utG~NU>;1==aexg z663lDt}}G)@fiRTyJ??ohVJvZ&?GVj>lm$xK#$a@zZ?8TGTc)X7MNiWrq*RX*276Z zoA1~rfObK833k$Yae`EB12F$S^jV!fPL)9B^yDOYyYO=aijgFwxM7kKYuo= z>FIOL#{O0P>+QF-5A&zjF9g+3m2b|ykgF@1 zN#1Ti#S&PY6Wdb_`!^(u>pdxbEzfhrqMEQ@d27H4+>e7U8)^@_U()6!=^$U;ImZG+ zN3!S?6FCmpT&J`<2Nb;!N% z<;~n>o|2YE6WD}6`JkC6fOBl>TdA4djtgt6l~yE3Ds`agrF;yHTJPBHAg#dQJF!kv zOqj;^i!+s6inmYbh`iXnc79Rd86DW3OZ9L{n74i7=twthhmT?x7SV>69+I^*_<`}- z1DmjUQf2sA@3k+ql*@(=M`}dMSQBUFTIrzKb*nnfAi4teL=A%i-;i0thlzA17jIbQO+ir4PhdHnNM5U2xGv0*;+ z%yFd$^m_EvA%p?-9I^^ob+%(pPG>x*!^eMT|1*BMv?Z`ts^ zgOj$F`$h*RP>&aWqAS?z_9X+$R+FQjr+_m}2ARo}pu@v$??{UTGZfa*DIghzV9gBD?SZaF&;`IPs!4G z?L8=aXtZb!-@{p<*1^x|txZ=s3yKd?+_pJ%|28Qz)oVDWPf3V zjr}4e9oIdjNlGPvP)osgrG!ByN<&2zZ2HFq!(ct!R^D|7?}Bgk$NCZwxHo^hyKN`W z2L&_IVn@Aa9%0g}JyE6ZtR~qStE?mv87INToUjvYu*y)fG&d*`4ifu<7vMZ2>hg_q z4~d^M%^$N%`F#2xYpWMhiM6_g*Z%o2S(yG6Tbol2w^N7fK5cwY1Fa0^YR4BU*Ly1j zKdy%C!B&B^hhHqMR7F1sI1vD&8J>pyJ7L+I`iy1NU7; zzyc008I^q6?RY(L1;Yu?_g<#@zOLL#IZ|}A54qXsy3!xO3D17)J6Q|y)Z5FXJ)4$I z6j(bf#kzDjm}8N0Q#8`jZ8resP>9zfbSOAQDtnH8cC$OI%tvGT#}G}yk4P(gJRoGt{-F2si8cY5uzpDLzNthV?4ix_zUH?0Ha2N8i04>;2Qz=WY3A z(s}a={^SGg$Lt2jJ`Vd1j$gcl3O!6#Ors`_oX5#+g0#Q;idr0rHVS*}#+^65{%(q! zlSjLMh3yXIklb~q3~Ph2j~c2RJE08(D@PZC&KjQd6<4iH^IQzByvjL3POx@#9q;Uo zl(2(j2ZILJ^lJ+3raq8;*&>V=Um^xj1Yj^iOUvuC{2uK>yjz{b#v%U=(oehMVANWblG_zOM{&B zK;81LnzU`PQ@=c2OJ2(4?2|syWy-}hGS-fgIOr)IRFOb`fCIYBXip_jJxDKvhAAU2 z?a1N<)(`sOUhrX0uAtrEIo76l#pqlT=Ot=n0+ZV6$y;<&1i5_ANBxMIXJrsv4F=ppib38sgF%+#y_O=aiS@ZNf5{ij=aWE4^Gu1Zx8Jhvz*r?k>WvS|o*h-!y+#>sDS! zamBl2-mCHU@DEF?)RNBFHawd0Ux9F zn}g3JHp`rf-g%^0qvP^;rC(se6Zxe{GnM}tico*sA?%~Ym|mj6a_SIshNBN#fKc@Y zjS{}3{UBfb@A}Xm{by70>{2M^A7vj&>Z}t zP__^G94*)L_%C10d1IyeR+Q<`s@8u8N;fXwOQc6~UlrNjXG9Vz&KbtI>p!NKr`n)@ z3*7$m&(f7kpWS~(*M)zIXbS}c6IU;0VV{)j-hk_A)!QX9=-NjQ!^rWAaHjSv-v@&ut274{qW`%PH_ARS8X2Xd4bxz=gv2k_9?A2H z%8K$f;1ftUk)#>EDca}SZm?|~LUVlbm}30@cX1Up=m6-G;%!z${yedoK0zrJg-F$E z1UV3reGTP}R@|!$58@Zy+D|u0rSY)HB%k@;7r>2&QLpzM>JrI6bYJldF^@}JISlU; z8swD_zt)~7zZf3$K(vs|qtxKgpL~UBXzXz!Ma%YoSB(C+rO0HKl=#Kpy>#x-U-HZP za8U?TqFWf>xLdepnM3!`kPHtwRZ%=4G+)F4-hqL*GBPs76R&ZK&yJR(`7Eie>s61&#JTA|Q-1ytK={%_pe{Zu_{#3N6_$W^?5aQ?ogxh2- z%^An}QAuZk^Dwo`2?kr)fm_GR60_V-9tQ*2!mvBh0qf&)q*$ClY*SM^e>MC)wXGY$4DuRyALq^PJrc~YX`KFi>AZ;hyOe#7u-$vOOI*U|}SZM!GK zRJBS6hc`CJ(tTC7v4ZiM|HcYV#$Z9w>o<7vP8H2<3D4`EXRzH8V$rKR9_Sxy=I*R$ zt9*Co}G5`O2+|s`C7pOEk`yuPDxEvD(@aQsP{2Ib2O#qo>5Tt#R#`3JVzHo?;D>zk6?IA>3~NK+S&9JI-})Yx*U(vgpHy z0?I)%QO>kZ2P`io@o-r{)E_3bC^;K>MrPD8a$GYpc z*|QC_ByPmVYoZJdxjfg*#`ecrt@u~y#;Th4sLXFSMun5LxVAb(Ztn@LKYghte~%iC zr#b{oFB-CH@?^S4vyIo{Q>^XhZ5}w{E*z5vj&|lgX*^!s88s{RR5^Od%k@y85r1FE zhSsdL$rO*s_?ssI#p>qr$3Dx=j-w#hqg8p>=UHn}6vW^9IOk(Up26McNc)|=y(iC} zRrl00Xt->;GPZZF+Z_ip+GN6_|C(kkI#@c-bhLY_?oplNxhp%hIh}4sLKxj4$H+~h zQU1=GLAGQiY`f&>n{0?lLe6+@v@eb8oZrB??e`=50gW2{$T-Jewo(IU^ND;GV>QD2 zqE}9A1rKUljog-|`K;!)7^EurNLS`nfbo5Ei2|s~6&QX*)Bhpst>c>hyZ7-SDk^2t zFclGz?gkYFX_1l^k#0thvOq;Zq(KHq$7mQeK#`77W5DPd-J|386!T=n>0XD$?uZZIYM+mIVw zeZKf@XRYNDm=T7vczz2>C?{1ot%>inI5`d$h3|(zBdL4dnQ#S*6?xIcftCn=^YtQ5p1RMr1+_<6xDYI+ z`+KN1tC$6%<+;psk%SCgN_jrQ0YP+S+h$Hihb{3{TqrQ{SXtJb z=UiIroWZp!>GTm(d!$w=5`N88N@mHgM9318X!*Mus)saV6s3Bz)37@=o|V!-@DMNS zSw@=W6?x#f@$MT$6ldNX|LTD)y$pE7=3y1Xu&I1kY4ga2r2Mei#ry{iFFc4~bXEkm zjsD>t2U`(<*P1cgv*Ln$u~>BAuzNbH!A9RdJ>7D%x8_sZlBlsSjU#U}eqiTBL=U~= z=(lelf}LKWp=~IYWFN*Fhr`XE^m9{cF-sNHjOk1mX7+8gaTW-iu87)B7Jj-qwV8@r z+Jlci{2Kg~?)vz6oqjqI_q0)Sl8g-6z3Q9 zjWydkjLiENJ}Iq(jousRW&W6K3o3?y}8FQ8FHE z46^R_h&}jDJ|tele=7I#Wmm~jjJDcng;UJgFR`))7ZzT0j!jkP1cm6sFu%J4=Xl)!zrK|I2zYti`#Z7oT_WKOS*f3D6@ z`K9ejUJP^DH{Ew!#{0+e*6xR&N(uK(ZW(NE&_+f__Y}z)tRe*Hd3n`CnIv1`P#)8* zfkaoU@rN~C_QEIEIXw8wtWz;mu+N=lufcvPJ)BU9QS_L;#^*>4VPNXS( ziN;_tXG9_bGdsXi($sU%)Kgrs-M$uCZ}!ylfh8tgUpmxW_DIFrnjVCN#neZ}OAZ4c z(*!N`4jMh)S{T134%bzB9nl40)?BPp#W#Jm;?Vdx+M5rP#xIM8rZ}#xW@$a#xyLk- zYc5+fh0}Ij8+f+A@}?czOC{)1Dm|A!&fm)dGosILKRB_mP7vQRR;=!D-tlXe7?#gp z@_jryYMW)R>mu24i-`MysdKYR8W=pp&pdI@zb;khyQ#Xpa4X2TfY2R2?X%sgdlcam zFeY6+q;1lI7Pzw*J*=}n(lUHBKk%NQ9L+UZhMTM0dIgf^Ya#4V{=~5QN}^h3f2u-Q z;#2C6LBf{Z^|hXG_~h)YVv@0Qse?J)@J9EfnG%cF{spPyBPoQRA4{dze%mG`BZ{P( zErXObi1G$Lp)|OA<;n^rLa#l4=^%9ko&Qiu zNx-T)rw37|S0SkiR4H!l4?sqTd^i{9vmquRP|Q@T=sneM&12Zo1mYaNR%=8*oFi8~ zpi*nj1hG9i!q4qwThr$q+p^k}#h2UbOO!flDrRC{>g&s&`k_51D-|vmJ5RUt*xCjQ z66}4X_oJO%t#AwwM_%4l^r8FFkx!-5orD{-LBw-nKHKNRq-0_~t@#?J`q&(>V53Nb zLLq!v{w7mzBvW*9FRwfPRTT}DPwjc}>ebW0){wgjn7%QAlGA`mu{YJOX$H71D zd=hP80R`Rw^-7a*R)n`MAoD~pEc3(+Ep6c_6JrMNU{F|MRA`?%Ayu#%><$Y$^%XTM zfLasj+RF5Q{P;lRv%>9FF9-a28I+T1gw zitjfmb1q1!t@wdA6-L&HIF7as!LmPo`UD>6p=SSx(|g)`4Fj(yq}>7 z_ugH+IJnEqy4&_K3ogOV6jVr(9jYcdl8=CJg2wHMHcfO0`lhq^FRv{NDXD1|P?5^p#8Uw9i)=Zs*KBQ) zi$(ZQmFcS%uoPJ=2(z$kui^W+O!&6Qa%3PJViF^7la==7o_W zwA`V{?Cfl7T0-;Yd_!OEGIAzI;H|pRtV&{~IbO|Gf*J3=su3*?3o+6LSiiaHa&c#^ zfm_tbkzXNcLms(6XzW=sbJWu?IpW$oIC$m5bHqzkH$M;Y?COVSP%(>l)gA{~g9t3b zg*Z8_%`I~@>bPAFQ_oiX&ocpj97c6fNv?QEO`H<0nLxpX-D|)aJ1V_8_W4R zH3G)-!he=PyS_plsKJmiD&8~cn^3%qYMprJ>*ck2L#1Z_Vz8S=_@w)q`fAi=jorM9 z-JE1yA?+$SdN_i#BSAFm>(?uy(44DJ48_4^+nVdtJaNEf+!768G@~O}B5DYXICn~R zFSvgEc)qXuH@iWfASF!OZPm`JucfaqqNRloQe0fjJ>WP}^P#_A=y_x3^0Nn_|QGO#)0ej?dByApCD!bMu0a%_a*r{Ws~M zfb$YsyxM0BGi&%!S*pEhV|xZI5T)2C-`n=`QNHonwEiPEyenq&*& zDwG4fBu8)N^$(#(99jINs53`VP=;tQf7)k1lQ|A(bk zy<(rg+{i~A__0)YmIw>nRneQ9Cl;adN*!)}0;%@rlU-=sc}ry_Wxdl~o%#)9ZxD*| z=H|0LJF~kG6*TNFLkIwIT?@dvQ4U2JB5n3T?#Ou>S~*k&U6t$VgsV)9!M_01vTdrx z^h1vC_h0YiQ@@RE;|@C8ToToqbA%Zo^E6AIyy*7q5DQ0U%?NwRa>s_hmvMcy_ME|P z@LhWE*9--hpG$VM^z6h|`!zp@cWemQDckq&>ca6IJ-bT7=3PYu$$=gb7yH%Rlq6m= zdCF8Hybc9a;)R|u<1WME2TnAzPQ<}dyLo%hg6lUriO=8XI+?~$9B}^xPq^3Qc-9@t zhrT?)!OE|;aPp9;D))R5Xr=D`r=ukYD>nA8cH7#&$x%aP{eG_1osLN>uz$R&TL`{I zup>O*yRQtV^ewFOc|B3j>;pw{sK}NV5UD8wK~9CR(>6jtAP_X_YI7z`JR^8~`{Iqn zhf!A?9eIJn#KHBj34;p)3>$L({Hq-qJ|hPeU6Ux=GA^{(?qONObkyvpXMvgQXf!&v z;{I4b?62(}5ej-GChbz+`-ni3!t3S{SC^K?07f=v6szH>v)S zKfqd&mdd^JZUJ?5Sl^2m_h1YS5d+*`w4w>KwCfF<S;kjj!hqS)diIaDl%QQ3Ph~vIPy_u-!*)C>d*^| zRS8VXXTFQn%guoy240($y4HOX@xP|7zvPK-1tc{t>NkklnVA{AnZD$A^7Qf@L*6O{ zxUG#|M~GZleGZE!U`x~U8&7kW{xm#cTAb8{wtYuR+_){0K?*oQN3^(i$f(}#Kzix6 ziVjkEWRKq6c}&`=mO@7XsRL_9-q@R3g6^#yCS7G3>F3*>E{cFWefBJNRHZ!gr-bGj z{c(*8CCHpJH3TwqW=7vnBxHGixyryk(m-8Zy`&QCA4pKL4%0Kst<6@{%j@c#E+C+v zDZe@cjlt-~$y`Ze)?v0? z;rH;1QG$1f7?=;n59h3<+gl_ecXMh>+n2NZY;%n)FuR7TgEp+ya@vOs(gG}er}mm> zF7{$zT-Ug_AWawl@|*$vvnD%wz*4z z%I7M}YmW+~T%Bf5RpE#wqPO3{LguiTTBd58z^A=E&#CEYuyjU?A8AsDNK3mH&1=&2 z^%m#i`lU}-bxUq>>hQsL>;N~4OctkO2>7Dd>QmP7qIpcl>l_0$b-GOXfK^93@1p|T z^t9PwbACY>H5*&{%XFW}|$ zESVTuP+u7#wY4%JaK9&+Omu@W1QY1N_BU4k4GM|GF1wRotIqswKQ-l{TqhliS`QK> z%cg7LtLKxG>$^$+4ur5yfB(846)1JEnE(ZeYbbfwIL@ps+NgSWv)$1)FCV_s8f48f zQrfl>V(4YhEbTZQ(bzN_MZd*A2iWbt*dYs6!5=x^f%r%Yc<6mKKB#_&5h43!_Wbp} zccZ7vsi1b>V2_A&`~6#W0V~+WbxbXb)be{9-)kk*;eYG}$y_P| z&pIcmx4#Bw`pU>-Yj258s?aeCpOCX8prxH?9h{0AOmuTJ;^5+X^Sk<#^!5D2iG^Fb zWSw%V{>Q#w&%_iJThlTv!A887>10UF@|kT!yaS|X`-cv;4BNa!>_)!Ir)tb;2VY%GDJuB zdc==?kOYv5t?~r!z_q+(8^<8}A)Bzut!k}dvjK6#z@@_4x?#M9Hd>dMZe*dJXl!ui zRuFz_YcmdEe-7yy0r5qhAL$-jLe$mMqgSrulak^ic74GPEUelD0XjK}Xk8;XEBHXc?;4J)-4PGnt*6 zt(ghJqv5AG>{W%6sXa@^)hC6{)AAM=1akY4=nfwStb2n8M?;*B=S^J~yEBGszJ>hl z?R}Z>Zl|~S<;2T|zCC|M#cZrpNPDhL)6?_|g+SJ#q4}!&pH7hRdy6L(B?<4c7A4dPiz} zjD4q#O7*z`58qzEQi99_h2eLX5q$skhUEw_E=GB%PA%2N-7>}mSD3|s4s;*YLJ>-q z9Ne@W5?cvMR$+RY=8T=s#%H4zh~6iMzcZBz{sM~9BUQm+`2$nr&_LsNu615^uSgwNu9qNI-O(Jpp`N-!r!dai5jCBRpg915JNufH&=GY4L< zs9fEFkU*CYoA3Bw#8az8iaEur3#zJcFQA4TD}0tq1-I(*Q_|8tB1X+t7FSmC-CrHL zBV%2fpZ-u|-@=TM0!LzEfnZ`bTzCJPhqKbHe+8uarA3Afl3_3iH|Cx6?Hd=+d5s{1Ar*cd>o!}IS16JJU>zNu%avoJ9}lY! zhA~D*M{n%w2C}bZj*0i!F+dE4OTW5!%jjw5*OZ4MP#gXRvjcliZQWpxBqG96oAsg0 z(tcmndB$A#aVw$*+|(d6d23Iu1pxEr&e+@e@^{DZts&j<65Cyw+Cyiy-BB1B#Miq~ zud_K)kT^&%ISx?EH0vmnvmQ=!E<3yg^#5K_YL2R9SQVEX7W+wCyQVHJBDZj%PnsuC z23;+<7UD5fIURCd~RT($9!lHBjpLKH6buszCCuqrE$scf!)o}ZFt^QeJ zUcs|;m|JFVfq`qAfN<z5 zD3yw_d@~PS$vo#5w}C~oFoY%-4TCm>8eR4|!BXcPO=E0G=l@lw-Kbny`|2y5=iU1z z#2;B$WH3@=_%$=tX8Y7-FHpSO+AJ~o#j9EpucPaE#b}bFl-_oIJ?z;HXGv#g=c6r* zY)716P$i5oFqcApC;w%WL_eJrFQ_vo{<6P7g6yp5!|-VvG>@Ik4#stmau>eUx?f^p zVX=Vy%tWZO3*Dou(27Y?$2`sKi|Y(`_{qNdH~XnPg&=i5V@yIuuDXc*P^)9^$+?M1 z|8dplTNX6dDugEj==<`(OQJ3KLadCmQ&ds9nEdQ*h2A<-J-$8oH|fD9;E%wdOuPOF zrSRef1Y8#}uSFr?uUjku!4H0={{5;tgKd1CgIn% zSk*?L#`am>OSjM6Ib!-@>1i39uv@Ex ziS+<*d6}mh_p#+`M?q%nYW&G2yb02YKectuTM&S0Znz3CiaJ`>3!|;wHnRN{3W};1 z$A&GICt;iY)(j%sW&?7&Qw!GnLg?yRmRr)M}C2pJ|xEHrY@14SI=gLaVOpct{M-Iox$Nto@I&sA+~WUHy1 zkOMMezPpyvV@%?=jf8bjTuCNySGW&waZ1>({SvK|nGSP8cr zgD$yCcT}{sv>v$GTIS0J^o7*O+(66=#<9YkGtcTRb442cC z2~-ff(c0!WCI+Y#5oOZuY%@s+6|;;3|6e^tMUEgUC|NQrb4OT0T~~R~<1=6o6!piu zC&4=0_SDiejAmlv+_aeS$c=cqzCqT-iho_Hxc45;s0t}(rI-+UsQ1nSI)@8os za29O)b1US0oNw6tGUMv37)vlyS^g{1!|HG7|acUgSFQdLbtSX zd3=rYMq{hDE3^H0_%xdiTF1QeeoghRJH^G(cF2e}LHqQP(clP*d1l01xpuOG1!kTn zR?cj#4OZInD$AVe08uY|akn2`wo(n%Ep|LLtwE!`d69%!XC<@x zP|of5*g;cVu@&_+p=m%WhGj9>UW^zuDxXU^tIxePehd{C_X23HHN^U2*fd5AbO4$? zvP+wJoYN@qFB#7wlnMTS0(3;z)bv`CKatb`wWjmF`Gq8i&j`*k<~gflb35AwSBYTv z*zk>N1xND}V!ZzP>Z#}QLX5cStf>&%xPZyTjreJV^Tw~$>=ov6bQNy(IxVfjn>Tks zN8pZ(45GgNQJb3Obtn`A0`0kq%G;BpeWmr9?e*#TE9&B9y!K5DY@cQPPkg4P7X9WQ z-}#G8`St64Sd5SA@IFPnsAH4w?uhAtN%p7hf6oGZ&oLwf1_=Wpn))*P5;eJYG<66R zQh!i~a+;aCaSTxiO?*2V*f~%14y3HyzUlrtK$cmOZjJ)(xbd!lpT_226z;qrmyWBo^`C=P3F+uqXDipPLw zU;FosYU2iawnTiwTE#}A_5+}tMMfH5~U$V)mqZu z^vpvC%s@>LkrhR$)m#g(J=l3WnE?Bzi4@w%Qf3s$gcQV=*DNL@v$ z<__4so}OC)vW+EC9NlKRIzlvJz%}xnpT~{o-xgeYUtE)x7MY}Tbe4#ZACpi~Bj>Hq zqNhXx($9EKN|KRpTjbT=oFM|fX&MyTFlv)JBL6WcStl1*&rd%FNhD%s2mjpwvkC(S zF3GDhchb!3m~A*Xf;V^R&^p5 z&1^Aa1@B-UPw!=!?sXP_@n1$hdPP8C7?`BIfP1Hl+A&7#=l|o7IcW-V;0t zaNgAIWzV}X?f(+&qXOxzgsW7de(2{lcL-^;KV>; zDTQy+Fmwp}!ixcBjhU22P6W%{P0wTu{JJ(?K$~)Bu0b>eD*09OOXiuR*|0ReFH|a? zoox*~e$ZWORh^cvCLS?sXc=}?LwPiePdD)lXMOKyRrvcMnJbM@RnwH;+iSSsP6H3{ zh-c+I=QJ`=H)~Ljy4RputUELE-xJ1f>R0dB_`% zZ(9lDpi}Ez?l7(j@(cKHzxoy~QQCKbgMP4}{V=MNeJ!M2`{6B{GBfGt%df& zhJ7e9gYvce!ond06QAJE>n~hfwj#Zv91?`amTTa|&*{p99ZxT>cq2iDE$6vcOCNS= zxV62vm}I=)R~B@jp2Jkf5pC2A9*KkyGldNx@IduRK;k`aFpWe4f8SipKvvcySB_hU zkl~!_)%VW3W5Du{r(joNQo=BoTvvY_O1&z4!>phYc)(mCz&>DhbF>$CS-w|yQmf;2 zJb5aEieJrEu$)*Jf;b%=44QS<%PfyXJhHK2fSDk|>ik(jzfMsVEz~y9IlYq5hXE`d zA>4$}c^EZppA-}C;!$ZooW}3i1*a;s3lrBr8Py21i4Y`)q?-4z*y}&*N%3V2Ws?4V zbn5p}KJ^Y)Y30l2_ojQJiw>`J+$+m^Mpg(>wvm(H$gf=SB6jX_^@0W_;WT6P;=kS4 zTIF=)E zz9sA02kzc8&r>t3^YsS1N%#*JL|X6`Jm}LWr!^x~Pnz@hgsx%d^mKCzYDaSm$Sg-QTZRl+IDDysu7?K(%JM_#}Ojf7BVVf-j$1Xok*g75Lv4 z7k|bf$Pf~ErWFWC(KuJ|s=n3ER;s{IHGtih zh{w$K1AL7;Xwo+C0S(Eyckt83e^fA@XLEBi$_LEcOjT*fEsXY6hR^Y!MB*i9=ZtK0 zZ{EE5P|h#DccH_-#;_AKp)7~ZR`+PNx0Zw-iHV?pnDH#wX*Jd- zViZ>2{?F7vPEC!W3D$?uB;G~zmX=7Q0#gDVzWD$@sN6AqUjT0~ZHwf1ds-O$6Y4Rf zg4^q|y+n6Qd7+0kt7UAl_!z#|JcR`-0P8irwbU5!inMWnhW; z*22868$%0)I%e(y12F~f=vBqi0)b1Y@-KpdQX75KBVX*CPJ#OV?B8yE^o z?QK@QgKp-H+C;)^GEX})b>Gl|7|U6a%LN>U@WcpZVEP$(bMrP=Ro6zizaoNa{BVUI zmz{fHJZw>}SgjJ9lMAOLj?NBHRgWwd)Eu2_Gko#SRECX76p5=@_eezt-6PSH+^no* zudO);aXz$hmG|N8aB*xSJ(!=+tq8G=}|%z z6ZPq<47J2IfFMSQx~qSL?~giD*Vg*k;cG&Z{Eyn$(0_7!)2#W-9IHY=QTGg!Bwz)Or8>46!_dfX@!&IX~x&VN6q;JhLwzk4dNUmO6sN!I;ldgYTH5TqY zXk`80pRL7UOP+frt)hfb*>gZ#B3b`x^U_=b6TIZ+bvWX}RP{#_@>9lln0p_`uEC9; zAmBdBk)1dn*1l&DP4}pKT)K4iLs$Wn-a0$)Xy2e0lUd&ujXH7qmm^-+73{`vZ8cDd-SDVqXfz3#C zq*LP=LbHWB?VC+0epTZ?wrYM^8E#+Q2GdM6J5x7!hIT2Z9cKeKQ0EH$*LY422grF^ zaq(S6qh9Obgck|tFX2m9TDt5Rjjlh^&DN4S{Np1Oe{mUK9RaP?`<2Hia3nDm6hbnw zfe#Sg&ygqRe&0!#np3j-koNJe;xc|=X^2h%Q3bC$5 zrg?2=-P@yQj#Zzaqvjp5-ZG1&V=3*w=WRb<9_X%&3ydz~^Qq1la)MO3uK=*sd{yO| zjo&f1>FN`-apNJVG7c145@@8Pgk}hYDtn-x+_X=OPYI4crToqZ{Q2X9TG6~zSVyQp zx?+hc9_ejvdHk1*#c!{6K`PIW|7Vssm%VI){yiwG3-?@nRYsTxaK=CFkfK_xcK(8JdS2jh!7+ z|35qf`3G_3E0TRkOIe9#*M|1yp#BoeK{TucYklscThk+NBZ^rbboYOSjc|@gfWtEV z0uM+sHUJfM*W1Oc(g|ML*Go9XzUQ;uAM7SaXFPU|3W6FZ8Y`^ezM64-lB(K%z%i5# z;WCa;v2o|XsM{H>y`QfX9}=>sc~UZQ72;4!E_mx(e%j%^-Y*uburK*L#3Fke3)X{H;f8y=9rtZg&YmLo(h08`h00 zint>CF&c>{nV3w;j)EL;qedG)Yly~klV7@Y7rd3n2)?;nrQIfXIqHJ2LmT6HzFzf4=K4;JCHJ|JW3rIjd|CXB&p!QBReLjK?~#Dq-Pz%XOE2ue>D*Ud zm6(Sdk$(PW^Q?|UZU_w%RF=_yZVlRJ)62tXQEI89Z;gkyn6At38snUfD_Uz%>*k=I z#3FUGv93!!)B!+apL@>$TZv8R=oNApi9Cx`5f`q4F5k%F;+MJ2PG!Zn3iBOYuX0r7#=dp|0WXydF_fp(z>a$UEw9Af4)IO8M3t5(@S#5Qz@uoCVI50-0CiNKn zez9HmciV-VeVuO%cpV)PzRtCJ>ov)@lfG?l>G5LD!(YHupvI9H=K&rfq4Ycpq{l zm!^F@s!?uOZKh^410MzGn|VgUg?9M%B8HS&*4_;o&aJP19s`4wbO!EFQ-;mNi94qB z4EpV4$YtgO+o~e#J2<|!_V!5PWVptN$gE5Po*d?lu9c@2z`D|T(03XAF9ACHPWJ}e z6$|c1#*FVG=I5=hv~Rz?DM5SNX3jFUX|zF>X3ar4yJhUj{t$0>Oa?wNXc%?tESS?b zrelogYmSw#?>7#>8~o86Q3hmz0uCc$zfx0y=66}FFyfvap&vl%wSK>bO9AOdI2k&t z=>evncf(VgNdtF@b&hqfbrEZ|$9G>}Vxj&Fy<9)#VM5sJ`9Q^tAF*U{Rg`hd-WC4v zE*Q6lq!lZ4L>2SgFDIjxK9GV?clgA|?T+S9q!j4ng6R^`NW_s|+(HL@lHUbZOd?0U z83av`TPkPP$ktMc75W5NP0?T-e-_$dMXC01(Jc7Rfn=krAh{Cn@wg-)acT>3P#l_i zx6AWfh`d~Lm-AoZyz-w_dnIpxD~LVJQk&n2@h+Jxk3kLv=eX3ppF`?smDexKe0+{8 zd>2W%z^CXGM9HT<&c$x_96GLJ@{w(B6~wLu3KkKD0NaaHW>%-9>UBby4 zg6NE&#@U^Zw_xqI$a@SJs!>n&!>t#G9=~%(x0Kd>R#EIZD%6FZZUV6TWu|i-aUDO! z`?Adn+P*0uQUU316H4;mWFcr`;<*oZa!-2*@xS*Dgwx#cp{`#Sno>wlopyaoq9$+! z?R9qqSvzN&eb{WTjWVdK^Fl(I#b47%k%2oRT6cONjnqe3?uK?+Bqfa9k<hkhX071?3A3aJo7g>yfEF60nEOlscE!m2AkvxmFeyGu z3hHf7R`&nLk#~(^9c9vXjt&ky6MNlD5pQbZn5I=z%74=C*s*cQQp>86HkDenPIO<2 zH=;<>omojeTBe=f+%cF*u@+$he1IgjWchsEYFDA{I3pFkH+6Gkqqxt=4&Oz?-0P#o zA;MSN`~pFGX%ow4o~!aw#OJ<=WmkNegU9sm6 z+EX9*vv9*dmQ&#H_dlF%)*;yNa_~%*(XwPdbF~GHH7_r5u%LS35QF4#WVx=!>MuvV z3v12feov4OqB@d0*uM!X@Fj{%0tU2rBrT-s>lK;P8KYc0EzMks=_r(f-j5k_jr*6P zlvl@HBRxG1$#RFn_~v}(1Uf7ojdP-e;|`A?fl^DLqFWx$K^@&B8!_)t=YV{+Rr~F$68sbZ4kfTJk_({ zww-PrnRI;4zDXa#@N`7&!)M7B-hs^>-pmy$1Zms)Dp-u^Hea!lo}2YZx6_S>o3pIy zs3pZ0a1}MfT^S*po5|<Yz?jfXf zW`!xK9ZBe9MDeIRRNQLEg62KT7kZNpG7%SliJGVs}644D2t-s)@&md5(4CKgi24 zh}ad%sJIz%a`4>c?5j~YK0#M6&RgYEz}+1t(+L(X5*r_fTmV%9^3@5jQm>6N>d2IS zRon;DS1^waqMOf^^AOoOdB~nvB|0n#hR0?+Q`RlCTKMW65tfT>{GcxI^*?#to&2{9 zw!gm*Q+&?@LvoaiB7ER>1(t5VHF^{GjKOTZ#{4^3P;rSTY@Fvx*(}uxJBMu8E;ZZw zXtr6+faUGvyR%Oe%kX-AsbzPb$46?(!d-WvLO;KEJC&H9?$)PvAe`CtSE71I2QdYv z$h9pHh&4w?Ts3Il&np87v4g9wp(|>s@`0P(Tw)(-O%4O%cE>a9G>whrKU_rY3ERz- zPq%f|3cWo@%Js7_xFy$^pd^`e?onv#4q(LVjX!o*hGj(A@$XV^uD)3-T+LrD;z9qn z;7RY*O8R?j(e<+xcmiHo>X1+7-tIrEZ!(2ZZBJys^E-c-t(O$vK^C+#U}Zwj_Uy?0 zez<{t*>w546fR@fz@(G|)k<}*#H1Ky)>Fv;DTi*JuGn0@%j;wp zg^S|l(_i+K>cMiCY~&Ob`2oJXZq{kIbRNv@&7F`XJz1H2S70J{_ik#``TLowJDo{~v6;iEZt84ko{EUY%dx`8CJn^}SVpUH{zhes_Hmy$ilJb__$ZE4Q5T2qrpy88?ca;?vh zgCfM3(Z|Pk0j?^gx$1REUA=v?*aHI|D?Xf4vw9t;xeq@bOKcmDSgmNDlUc1i)fn^M zg`NG25Bi8#vFxn6d>4is7O%5+P{5nmZ^gP^q*xuHr)Y_&(mh3#8QR;yI zJ-6d5eIT%Sa9PNqwu<|-jSTrTIz%ztTYL+fR#Dlzz6*?(5<6O?sf%OEqs%~Oe@F-tu$!T@STZPgXqF4>a$e%s z+Np2AIN^Lt&MI_YhC%Hb*d%-X^MhGp_=m&Dx>G}9@TNzY@$o`WbzS3*wD)c%u$%zc z*5jL-ml+0A0T(t?pn`NKzhgf|>~pc`u<+6GFUsFniEoR9v%HxMGD%3+L%GkUZzb+i z0JTelS17Y*uu=A{LEnclM(kT+(J!ArR{W%Qu!=nL zvQ>gJ>|4c(*fX@p@Otd?(~t5KNv@D@<*M#BX0BKLznR&Z70FW$I%_3z%7)2SfG^3acZKS(nq(*^bKQbYrM@k$nqd ze%rV0@g5gn_cEV03zG(ghx;Kie&2aoZe@-0!Q_|P%!VlyRwxvlfK}{UM2`}uB;Xu#io%Icid$E9fsQD0^i$)`;;tL9wra5zl(`c>K7 zhv+EVQ|@b7<-VkvDo;`)a(V;kCQgO0<>tP=;QY~pZltBjY&_wu$;ABRF%>kku=5t^ zYf;bg$Tk0G;7%!Nriyou-m)_(etQ|{YV-Ap-wu}%A5v(m3NlE{Z(WGACZF$-_{f4h zuJrh5dR!Fwge}%j4)fZ(bcgKqaH+Kev}#nSTQ6#@_T=g1mhMq!k?p{laJetifg9wxF%;yr zAJXXQ1)pBReNVWrRunHnG!#hkwcD>n*G-rs5L+~$#3k>nzuwDorhp1}E!K`9cJnlw z^>k^tjZEG4w>hSll?V=@9UczqGS~ZQK-B+@npv*A2}ZzaA3l6Y=RZveW-bPZcP{_i zq@B7l=L#7emBx}$vvi~^bD?I(JMd(H<8~34XTlo7y1O|)UOg3KI4r;Ow~lk=&u}-- za<9)gqln$>#r|x-WGYu;nbNs&=dRNAe|#(_&(S_^vR?dbSTIw)$bL)WU%4Fh+P9SzA#&=)#Yj7}~xJ6B) z)M7dto853>yt&CqfqZjpOhQBOXelQui5eN_}(Nweg5G?F3=tEHuhgo zT&;m$L?2R=##$PKB?y>Rd!OT>pqaV126ntQP2m#S-hO9M`sV?d^>nN=>FQ#x7V|xz zh`&fV-;>H{ROM>1o_r!?JDk?GA}CO@cf2diB<>RFdr1BA#f#^75#;=Ubg04oZ>f4E z8D*~b2f*ws!q1yWA(TPhYq->laon%uW|{u*lmCG!Cu(g)#V;&87aX^}(VNs1ayH;N zT_qAX3xIY2J_%R>6&}9obzo9}gFTQ8u7sCYv7I71pLlYWvtPE1`R?S9-RP|z7Wi?m znZI;2*lw`!9T@#bF*VPEI(%*D7h9HATE;z1V+)fPBYL3c^t9AU(MyjWu;(~RNn={j zq`i}J4di(PzBxvdJ?w{{OylYb)-IYN}VjE`MMRBnWZr@CisOLm7;>Dj4N?srf@uRngrBo~WkKRw+hH8pu{m_Fz1lo{6&yzy_cm!$_VULjtPT5HAVf&Ahd* zGPb{x(aEk#Tu%NUNY%Ym#`?vU)066ZM1-6xt3SwZ@fN!({ zbJn?n0Ar5_Q!TQje})c*e&EzR-Nx`1?F?iW1ST_zzOhJOH!(3OaZB>uDI2m)RKvXg z1dZh;r*ddI-W_cq-93f={@vLzfId0!0keLFo)<$ar+2>O866AS>L6bqoT?&ArvFDX z{>A=YWtlHy?pA#M{Pjo$*eQ6M;QAQRzU4SKP5S7uwZ1S1rHhLlwe5qCSq9CaOvy$; zbgS@rj_8v$X3#DL+kgUv66bn23b~i0=&DznLCoV^92s8x#Dg9Mbl$Klltog_Wiy?_ zD}MnO46KKt>NQAnXkz_%-5s>Id#2ac#KWzgg>CRGih#7VzPE&#?ka8NHxeFciV;mT z)_`^G!Kc%+bN)2QEexhGv#TNAv_~_8n02ToT9`A$v<;k8zWe+4Uc^entD1Rc^V+SM znG%(XSvB+HCRKx$mX4PL;87nIB`dzZzIxlgpMcLHsc@fpkumC4Cs2C$X_?9I(3etF zJvA71#`pzhWFRbYtLI%{ zTUOYI@nh(!)E+Clxm=yx$gy>L`Z#bRFBEBU!hv8){d<(#JL%KqS+IsgUmkTk-gZ^mC0tF7r`ny}u&T-Qj_dLu;_u(SpHfkO<7P@M_L0XhQWBCAP$+uK zRXI!CLL(_P!5}M>lxOVrw#t<&bH0(h&(y(h z7m7Y$)7-y-lHFP3E1ned!n`WbxbyNxn4l!fou|iJghdl8+?~K3=IZq}11NT}*5BwP z1izWj6zgum1H0^S7QxyERok}UGOK~H7cz3sHFV>$tWyh@QKlNRr{(YeucvE|XX^j| zQ+-lOq(ZKhZtg|yHd3EbK9O9KF(C;V*(5fmR6gZaisiOR?rO{3%%v!Do!i`oxn*p& zDQuYWJN5bXJ^!6Oc3$VaUg!0Gyr?zUiI~yCZ4?oUbLXm-E1uQx$2`1-a<4#(#4{-=g2EoV zTC0Cf0Bw^b#^&ueIX{+{y;|~=C8ecXRT4~FfT4=^{*XKL_yHK|Vb_Zp$Hl(}i#rw~ z{71@?LW!=-XPcc322ShUQpv;>ss|n@kDCrGu|8-Nt=C~Hkf%4;+O?I<@%a2DrMNuL zX5RY3lvtgRb0P+TVFx$f8_{E1mx8L_d2QV-;Z(ECBd?dO%f$G{(!f7fRF;@?b*hv< zdvKt{9dr?}`a|YT~~^-Q487_|cf?^B(=4NBH>W%dYx zIvwbZ5uUv8}db8o~ejd2rA{i#HqbTY7(ZOJh7TyV^|(WkfP zErj5O^jS?qFU;VZ( zJBJkVI;%BZQ$7Yj^VfXfW2_F2Hm=8m9ooUv`e%s?2&%Qg_mh*Z9voL-Q0Z^eG)s#l`lV{psvbK+hn6= zm)%c>%zXtiyOX{iyYKIrr6-h?A>;9e1@CFK3}tC;SVJskQyD}eg^p}~Qfa-)xcMdq zy|QrlF0C#`*L(NF?qBYpo_jcAeZnecwMFEZqU@GQhYkZA78_7e=bz?ycdRC^8ISJN z80FRzw~rT`@YdaEVkLby&KSFk0qx!EE-l!(OT5_0@v75J{q|6Y*n#c`b-B&x>DkkO zfVRudz-(+Nr)c+q9C>zjcIsb3c5!&KmKVOCFfl+!Q`)1I15Z*~Jv@wUVFWKK)2xGc zI&8_ZrnUxXE>|2!4;iATW$_qy;M1P2y_}NCx022E*;rZm%`_l5)D30~EdRcO7x?oisvlUEvh z8xw%obNGz>-!YjY(=#(bhpx@FYuEHhVuv3K`hr0;T=>B9Y2ZYXFv()IG4Ptlb&e=R zhR~ty-gwN1_w?#uvXnWU#8NID=MKs@E%d!A{S|Hi5#C0$aw&2S8+rI@^#r#gR!Ogc z89|&Ih$eHYUum7r=<-!>pV?`Ul$PerTU&W%C;b^=N9;uH0%ml*>Tk$sIi(Y$qocpx z2k$;x~#0Zq3!DF`Afyqj*q}AI6yca z4g7NvmeDqTR@lIIBQmVMpeq(#U8_lchmN(g>;Yj=CjOHJd_UUJjADbVFG(CFiao7HxM}B_1A1dij z?s}p@*@BaEF?t^Jv?563J-JWR9QT-tE3F_0Ut?EaWTiqZ*+%2TuFfxgMT%#89RI4O z{XDu2X?|E&aIvPbHiVNw(oK2zrN)gB_y)!0Zp;`M9_*%|>&@^KJyUFU0;I&zQQo1; zz&hnU0KIo->S?rtoo>6%%*$oy{%7ZpUSd%2l`iVvD2Q-Ex(mzEx!Z=Z;JZu1l_<%q!&2?vcV%2l3PC9d(wm)&Z7o_}8(Dpk&1a!Ir|@c=+YP0v0wHwRZ^eLK@r zl35ow26@`IP)Qt=XIG|J+bTAq&Q;z(_zH&cBtpcZ%R_tR!uci%K8v|}&iA* z`)gM~O!-cU=*G21GPlV0+s$Bg)#4F9!l}yAN=GiW2%D!T_vrK4;^y!$euYa>p_p^L zsN-%+ANYx>ri5~ZgsSSMAar*HCR{&9FqW@me3bBWbBF=!Dy7sOx+G^97%m?Z=y&SJbY`{7fLWdA!67Cew6x%e>PLn4K- zq4+&9k>C%*)49EwXOqIXwR}&8*sfhuP2U;NMo!?$NFHCH_dYD&YZEBNM10U5Lq>V6 z`;qA%6+}g^SA??JLkDSC`FJHTN2e#PqQ)SMuQjl5v&Nx*sMLlWQvVi^VG$TbFN+2A z$C<>0hJ^}jJTTa8zeSQVQAfgUMVN$4-3tz0_S)H%(|@0H<;s=n<$h>+*s?Fx-abE9 zkaKy7Pr=!G6_+1#2kPF*MA!#SXoX9%-WGGU!lI&MH=;PV4jUXc1c8PYn^>r_g&Cvb zDY|fDbPzK2G~#-BMQ7a_lLEEqVZL=p2ETvToj(>K$P|mI&iAu@`8f`$wg^cWJK=25mloqL$(b z`QO%ZqOQY+3QiBW%A3G_*DhUNEH5i_ith~%NCykvLe^(hGIrtZ+}+>8H)%vQp#57$ z%cTz^ckd1Kd~}K^Gp>1<)aS`uc@{wMa@zddvU~Yc6`<$pZFM{bRK3O8&A4=tX;{ zTU{X|VlX?<@cp^y_&cL2X_^B>#o)O0jed;wK;Q0C7ij7IcaW9w*V+A&Yi{-Y*Kk*K z^h~FqFgL=hLLVNcq2gEL)s1fZ@eZmqkPuOG#k&(no$KuwE?d1PWKst-Jey(<9zdac z<6dbF@aDtqB#1-VW}B;T0Hw$+XX&#Bh?`A1w>jzcE#HP|F(O;npz)X$^eZLQ`p(*) zt=2-JP{L;uDk?RGPxBLMt;J(8Z)aw7*QR^J`vD=|jaZ_k+8Vem%JljD@V8nX#rVX6 z>4T@=O;w9$S8IcROU$yfe9NfnKb6r;2;QbQ_ew8N*C?&|$NTNoe}%0g$UDGK2w`I4 zKp~QNV6KT_d|(~~I$GgA<>)_HMg1{6KcwrCaM8`=nrCxtzaQBRdz6h@)C>=0{v%$b zRM>cNL-sleURSAESokQ_#5)%k&N1^~D8Wk40<4Z3)=l8Z_Sak#ObGe1nSU8jsP*8* zyYnM9ZtE!#Ym*cOuA2)c=JMs|io{_1cNeHl87Sr)hL6UaG8~jDk>{pd><4GIyxP!V z^P66)?pvO$z~frc7+*|r zJ|%1K>grn2FABon2o4Sw+a3h~2PB7gb<}SKMYgf3yWhDGHA%HFJNO$}lg_rb-nENL z_JAcwzQbN9pSj|<)D^||>&m>`R<1N^wftRsH2+s5z-yn2=Q9`#KXxjn zZ?uhreDA^OuC-Tp)EFpCqF;r{qc;_s3h~;f@gzb=62!%hj=8D|oz5HEF+0(ZvK#JVxR&zjp7Q=-~O4of#$}u&rx+ zy8*)Asziz3+-D!>>4oJzKP!OD&hXe5s^GCeMdqP3&a^;WKAk_h6;xKuA48Sj{JiDT z^Ic6D)#z;b3;R5_f?h!C>3JI!%*k6p2t;3Hfbue%cEYMC2#dw$-3+`M#-Euf1OgTZ z@q_6T4#5gJIio#wmC(w>Y_}3ieyy#OQ-167hdxB{{~n@~t9SEsf^IZ(#<#_*E!l@X zT&`NFxIMD-6PND?oH$q9P4UbjrO><)xedX@9TOtIuLA+zcJd7}tx+LQNa?7LmHhUg zCUC-nJy?8B_jdcY4W>wD)SJ_uPb&iGgeSXXoFN7o5UY&gGMcj0yxyMwCjollV{~m& zvT3Agl*=yysz1EJL3Oa?jxU`8G~}-lwshCf)qw$bDH5+|S(Dg)lC>jLn8VhDQz6Tb9 zXY=Z6==DIo|L$MagI30@-|HKsjI=8t(}K5^vCsDC6S;z=+e(-PMaBgmU4XF{pq` zOJGxHct#n89U14}bypStAq}#$(J(i-{)C)S%8iB-brQ}WNq&w{k=3z4s(_xKKO(km z3&Fig=%QoIzb!?b`IM9tcL;2|i+9U!K`txpT+mdiUD5r;aBI!!UjKSrr_&$0k)0au ze^uM%!yy60%LdA6&|-Oa(vP-5Wv3v*`AVz(FUSsf?;}h1{h$)#t#?=ykF0RYz6>kJ zm$LFv>uO#6htQfu_^-{QT-re*MIZ%oEoYL$} z7wsl|2oBLNYy;H7+1Xj+b3&*#Qjq?v0dWrMT!Zqe+1{X*8E#cB3{yiK51U6O(45m7 z0tFEa9^*#|H?(A6K1WEFLGRh}|AZquPimRl^jD0c??SvKps`m+(Hbq+YT*(+9Z7T6 zlmKs>y4@gGVOCa0aUs`v&L7^)`JM{C!MU$DSLNyvE8e{8X;oIaXdCp z5PRxd4VOd;E{0y^*t6ju@w&X5A!OVhi<6n2Eng^pS-uG3fpNIQcOC-Ph-g_|oDFio z|L0Z#qDV)A<_P;OiKa9+1Mcp4n6P>e2&qi#S4pFt$DE11F0j40t%^3rW~DH->RK2= ztZ834(ndO$+`-a!t5~?Pn0Q+4MbUMc)AJUSDE z@_)=QZ%*ojOcb<#w^!sK-Ac?ylrm}DQsQCiz$b6nKZML_B*#oE&WDi<3nYSCb-D@N z>BB`_N_OPJb*P14>P_&0`HVf;Cwlz{b@i|VM#6}CmQy8f{#jw)z7MKHRrbw)D1kny zX_@n@H%YY}VI_fJI}|<*-^|9@-zr>7|0q@!q_e7<&a7hq?r8`I9t|J*W8gq9s?*Q= z)5LlD^KcPVNgz$>=g~rs5OTARKYUSS)>Mc3(=>^qaPEv;xqWJ$R8^i74&`bC-4fjJ z;LokQQodV`6?WR~?9N$fh3BD0ALS#9+DeDA6wL)ma9JD&aWvInsH);I<1y{eHK3vI z)uLg>hpVR*UZ)Y$j`=d+nDn?>O2*8wyQ0IyHpSPd3>srGRBW)8L&RCjuim2kXUYKr ck<%N>x)cju&R4tXU-T~hZGE0#ar4pt0iOO1qW}N^ literal 73146 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

Jf8%VJH5LVSzy&`sO#wgg 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 oq!{28^HIByq;Q&LJu&Y&LsWU;+I=TYH List should render empty state 1`] = ` @@ -383,7 +382,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -552,7 +550,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -627,7 +624,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -644,7 +640,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -708,7 +703,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -735,7 +729,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -810,7 +803,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -827,7 +819,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -891,7 +882,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -918,7 +908,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -993,7 +982,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1010,7 +998,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -1074,7 +1061,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1101,7 +1087,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -1176,7 +1161,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1193,7 +1177,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -1257,7 +1240,6 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > diff --git a/x-pack/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx b/x-pack/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx index d859f89c8e097..c84287dad7a97 100644 --- a/x-pack/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx @@ -29,6 +29,7 @@ describe('TimestampTooltip', () => { 5 hours ago diff --git a/x-pack/plugins/apm/public/components/shared/sticky_properties/__snapshots__/sticky_properties.test.tsx.snap b/x-pack/plugins/apm/public/components/shared/sticky_properties/__snapshots__/sticky_properties.test.tsx.snap index 020d5952c03e4..f8799874408e3 100644 --- a/x-pack/plugins/apm/public/components/shared/sticky_properties/__snapshots__/sticky_properties.test.tsx.snap +++ b/x-pack/plugins/apm/public/components/shared/sticky_properties/__snapshots__/sticky_properties.test.tsx.snap @@ -29,6 +29,7 @@ exports[`StickyProperties should render entire component 1`] = ` } delay="regular" + display="inlineBlock" position="top" > @@ -39,6 +40,7 @@ exports[`StickyProperties should render entire component 1`] = ` @@ -64,6 +66,7 @@ exports[`StickyProperties should render entire component 1`] = ` } delay="regular" + display="inlineBlock" position="top" > @@ -93,6 +96,7 @@ exports[`StickyProperties should render entire component 1`] = ` } delay="regular" + display="inlineBlock" position="top" > @@ -122,6 +126,7 @@ exports[`StickyProperties should render entire component 1`] = ` } delay="regular" + display="inlineBlock" position="top" > diff --git a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot index 19b44540943b3..a891b7ebe7686 100644 --- a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset.stories.storyshot @@ -64,7 +64,6 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -92,7 +91,6 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -125,7 +123,6 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -158,7 +155,6 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -251,7 +247,6 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > @@ -279,7 +274,6 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > @@ -312,7 +306,6 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > @@ -345,7 +338,6 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset_manager.stories.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset_manager.stories.storyshot index 05ef9df1c8601..6ef6d19e446db 100644 --- a/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset_manager.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/asset_manager/__stories__/__snapshots__/asset_manager.stories.storyshot @@ -348,7 +348,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > @@ -376,7 +375,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > @@ -409,7 +407,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > @@ -442,7 +439,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > @@ -524,7 +520,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > @@ -552,7 +547,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > @@ -585,7 +579,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > @@ -618,7 +611,6 @@ exports[`Storyshots components/Assets/AssetManager two assets 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot b/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot index fdf14191ece4c..9c9ed566e9482 100644 --- a/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/expression_input/__stories__/__snapshots__/expression_input.stories.storyshot @@ -22,7 +22,6 @@ exports[`Storyshots components/ExpressionInput default 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/home/my_workpads/__snapshots__/workpad_table.stories.storyshot b/x-pack/plugins/canvas/public/components/home/my_workpads/__snapshots__/workpad_table.stories.storyshot index 0de7012aee1a3..7d05176b8147c 100644 --- a/x-pack/plugins/canvas/public/components/home/my_workpads/__snapshots__/workpad_table.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/home/my_workpads/__snapshots__/workpad_table.stories.storyshot @@ -443,7 +443,6 @@ exports[`Storyshots Home/Components/Workpad Table Workpad Table 1`] = ` > @@ -471,7 +470,6 @@ exports[`Storyshots Home/Components/Workpad Table Workpad Table 1`] = ` > @@ -619,7 +617,6 @@ exports[`Storyshots Home/Components/Workpad Table Workpad Table 1`] = ` > @@ -647,7 +644,6 @@ exports[`Storyshots Home/Components/Workpad Table Workpad Table 1`] = ` > @@ -795,7 +791,6 @@ exports[`Storyshots Home/Components/Workpad Table Workpad Table 1`] = ` > @@ -823,7 +818,6 @@ exports[`Storyshots Home/Components/Workpad Table Workpad Table 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_controls.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_controls.stories.storyshot index e70905298a58c..31ff283e7030f 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_controls.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_controls.stories.storyshot @@ -16,7 +16,6 @@ exports[`Storyshots components/SavedElementsModal/ElementControls has two button > @@ -45,7 +44,6 @@ exports[`Storyshots components/SavedElementsModal/ElementControls has two button > diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_grid.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_grid.stories.storyshot index e0ed2934f44b6..db5daa86b1386 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_grid.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/element_grid.stories.storyshot @@ -67,7 +67,6 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -96,7 +95,6 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -178,7 +176,6 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -207,7 +204,6 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -289,7 +285,6 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -318,7 +313,6 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/saved_elements_modal.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/saved_elements_modal.stories.storyshot index 372cd12db1b99..f019f9dc8f23d 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/saved_elements_modal.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/__snapshots__/saved_elements_modal.stories.storyshot @@ -294,7 +294,6 @@ exports[`Storyshots components/SavedElementsModal with custom elements 1`] = ` > @@ -323,7 +322,6 @@ exports[`Storyshots components/SavedElementsModal with custom elements 1`] = ` > @@ -405,7 +403,6 @@ exports[`Storyshots components/SavedElementsModal with custom elements 1`] = ` > @@ -434,7 +431,6 @@ exports[`Storyshots components/SavedElementsModal with custom elements 1`] = ` > @@ -516,7 +512,6 @@ exports[`Storyshots components/SavedElementsModal with custom elements 1`] = ` > @@ -545,7 +540,6 @@ exports[`Storyshots components/SavedElementsModal with custom elements 1`] = ` > @@ -764,7 +758,6 @@ exports[`Storyshots components/SavedElementsModal with text filter 1`] = ` > @@ -793,7 +786,6 @@ exports[`Storyshots components/SavedElementsModal with text filter 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/sidebar_header/__stories__/__snapshots__/sidebar_header.stories.storyshot b/x-pack/plugins/canvas/public/components/sidebar_header/__stories__/__snapshots__/sidebar_header.stories.storyshot index e01f34abeb9f0..130f698b1152e 100644 --- a/x-pack/plugins/canvas/public/components/sidebar_header/__stories__/__snapshots__/sidebar_header.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/sidebar_header/__stories__/__snapshots__/sidebar_header.stories.storyshot @@ -55,7 +55,6 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > @@ -83,7 +82,6 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > @@ -111,7 +109,6 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > @@ -139,7 +136,6 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot b/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot index 5d8efeafef69c..8ca3dc2a94d4e 100644 --- a/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot @@ -35,7 +35,6 @@ exports[`Storyshots components/Variables/VarConfig default 1`] = ` > @@ -53,7 +52,6 @@ exports[`Storyshots components/Variables/VarConfig default 1`] = ` > diff --git a/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__stories__/__snapshots__/simple_template.stories.storyshot b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__stories__/__snapshots__/simple_template.stories.storyshot index f4233e27345c0..ccdd0a8592f2b 100644 --- a/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__stories__/__snapshots__/simple_template.stories.storyshot +++ b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__stories__/__snapshots__/simple_template.stories.storyshot @@ -212,7 +212,6 @@ exports[`Storyshots arguments/SeriesStyle/components simple: no series 1`] = ` > diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/__snapshots__/field_type_icon.test.tsx.snap b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/__snapshots__/field_type_icon.test.tsx.snap index 769ebdeba9955..e69e2e7626718 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/__snapshots__/field_type_icon.test.tsx.snap +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/__snapshots__/field_type_icon.test.tsx.snap @@ -4,6 +4,7 @@ exports[`FieldTypeIcon render component when type matches a field type 1`] = ` } delay="regular" + display="inlineBlock" position="left" > } delay="regular" + display="inlineBlock" position="left" > @@ -84,6 +85,7 @@ exports[`should render with fields 1`] = ` anchorClassName="eui-alignMiddle" content="Zoom levels where the layer is present in the tiles. This does not correspond directly to visibility. Layer data from lower levels can always be displayed at higher zoom levels (but not vice versa)." delay="regular" + display="inlineBlock" position="top" > @@ -132,6 +134,7 @@ exports[`should render with fields 1`] = ` } delay="regular" + display="inlineBlock" position="top" > @@ -182,6 +185,7 @@ exports[`should render without fields 1`] = ` anchorClassName="eui-alignMiddle" content="Zoom levels where the layer is present in the tiles. This does not correspond directly to visibility. Layer data from lower levels can always be displayed at higher zoom levels (but not vice versa)." delay="regular" + display="inlineBlock" position="top" > diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap index 3f1cddf944374..5b43c5fb95560 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap @@ -33,6 +33,7 @@ exports[`renderLegendDetailRow categorical Should render categorical legend with @@ -113,6 +114,7 @@ exports[`renderLegendDetailRow ordinal Should render custom ordinal legend with @@ -176,6 +178,7 @@ exports[`renderLegendDetailRow ordinal Should render interpolate bands 1`] = ` @@ -305,6 +308,7 @@ exports[`renderLegendDetailRow ordinal Should render percentile bands 1`] = ` @@ -412,6 +416,7 @@ exports[`renderLegendDetailRow ordinal Should render single band when interpolat diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap index 631a6117a111d..11a4fafda29e1 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap @@ -12,6 +12,7 @@ exports[`renderLegendDetailRow Should render categorical legend with breaks 1`] diff --git a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/join_editor/__snapshots__/join_editor.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/join_editor/__snapshots__/join_editor.test.tsx.snap index 92330c1d1ddce..0a79b21175d1e 100644 --- a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/join_editor/__snapshots__/join_editor.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/join_editor/__snapshots__/join_editor.test.tsx.snap @@ -9,6 +9,7 @@ exports[`Should render callout when joins are disabled 1`] = `

+ } + isOpen={isOpen} + closePopover={handleCloseMenu} + > + + + ); + } +); +ContextMenuWithRouterSupport.displayName = 'ContextMenuWithRouterSupport'; diff --git a/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/index.ts b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/index.ts new file mode 100644 index 0000000000000..56c6009ccf1b2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './context_menu_with_router_support'; diff --git a/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx b/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx index a6b2683316efe..ee0bf02f730f4 100644 --- a/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx +++ b/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx @@ -153,11 +153,14 @@ export const PaginatedContent = memo( [pagination?.pageSize, pagination?.totalItemCount] ); + // If loading is done, + // then check to ensure the pagination numbers are correct based by ensuring that the + // `pageIndex` is not higher than the number of available pages. useEffect(() => { - if (pageCount > 0 && pageCount < (pagination?.pageIndex || 0) + 1) { + if (!loading && pageCount > 0 && pageCount < (pagination?.pageIndex || 0) + 1) { onChange({ pageIndex: pageCount - 1, pageSize: pagination?.pageSize || 0 }); } - }, [pageCount, onChange, pagination]); + }, [pageCount, onChange, pagination, loading]); const handleItemsPerPageChange: EuiTablePaginationProps['onChangeItemsPerPage'] = useCallback( (pageSize) => { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx index 5a2ad6cf4c60b..6df5413c1eb3c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx @@ -14,7 +14,7 @@ import { EuiPopoverProps, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ContextMenuItemNavByRouter } from './context_menu_item_nav_by_rotuer'; +import { ContextMenuItemNavByRouter } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_rotuer'; import { HostMetadata } from '../../../../../../common/endpoint/types'; import { useEndpointActionItems } from '../hooks'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx index c778f4f2a08ec..412db3dc2a63e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx @@ -10,7 +10,7 @@ import { EuiContextMenuPanel, EuiButton, EuiPopover } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { useEndpointActionItems, useEndpointSelector } from '../../hooks'; import { detailsData } from '../../../store/selectors'; -import { ContextMenuItemNavByRouter } from '../../components/context_menu_item_nav_by_rotuer'; +import { ContextMenuItemNavByRouter } from '../../../../../components/context_menu_with_router_support/context_menu_item_nav_by_rotuer'; export const ActionsMenu = React.memo<{}>(() => { const endpointDetails = useEndpointSelector(detailsData); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/log_entry.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/log_entry.tsx index b15c6b9ba0020..bbe0a6f3afcd1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/log_entry.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/log_entry.tsx @@ -144,9 +144,7 @@ export const LogEntry = memo(({ logEntry }: { logEntry: Immutable} event={{displayResponseEvent ? responseEventTitle : actionEventTitle}} timelineIcon={ diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx index 34423767578d9..8f19fea818fc6 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx @@ -14,7 +14,7 @@ import { HostMetadata, MaybeImmutable } from '../../../../../../common/endpoint/ import { useEndpointSelector } from './hooks'; import { agentPolicies, uiQueryParams } from '../../store/selectors'; import { useAppUrl } from '../../../../../common/lib/kibana/hooks'; -import { ContextMenuItemNavByRouterProps } from '../components/context_menu_item_nav_by_rotuer'; +import { ContextMenuItemNavByRouterProps } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_rotuer'; import { isEndpointHostIsolated } from '../../../../../common/utils/validators'; import { useLicense } from '../../../../../common/hooks/use_license'; import { isIsolationSupported } from '../../../../../../common/endpoint/service/host_isolation/utils'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/types.ts b/x-pack/plugins/security_solution/public/management/pages/policy/types.ts index 7d296c2ea0ae0..6d767df73cd1c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/types.ts @@ -72,14 +72,6 @@ export interface PolicyDetailsState { license?: ILicense; } -/** - * The URL search params that are supported by the Policy List page view - */ -export interface PolicyListUrlSearchParams { - page_index: number; - page_size: number; -} - export enum OS { windows = 'windows', mac = 'mac', diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.test.tsx index 0aed93500453b..3292bc0c44cb9 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.test.tsx @@ -98,9 +98,8 @@ describe('Policy Details', () => { it('should display back to list button and policy title', () => { policyView.update(); - const backToListLink = policyView.find('LinkIcon[dataTestSubj="policyDetailsBackLink"]'); - expect(backToListLink.prop('iconType')).toBe('arrowLeft'); - expect(backToListLink.prop('href')).toBe(`/app/security${endpointListPath}`); + const backToListLink = policyView.find('BackToExternalAppButton'); + expect(backToListLink.prop('backButtonUrl')).toBe(`/app/security${endpointListPath}`); expect(backToListLink.text()).toBe('Back to endpoint hosts'); const pageTitle = policyView.find('span[data-test-subj="header-page-title"]'); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx index 4538e86a841d9..660dda6493c39 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx @@ -5,23 +5,32 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; +import { useLocation } from 'react-router-dom'; import { usePolicyDetailsSelector } from './policy_hooks'; import { policyDetails, agentStatusSummary } from '../store/policy_details/selectors'; import { AgentsSummary } from './agents_summary'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; -import { SecurityPageName } from '../../../../app/types'; -import { HeaderLinkBack } from '../../../../common/components/header_page'; import { PolicyTabs } from './tabs'; import { AdministrationListPage } from '../../../components/administration_list_page'; import { PolicyFormLayout } from './policy_forms/components'; +import { + BackToExternalAppButton, + BackToExternalAppButtonProps, +} from '../../../components/back_to_external_app_button/back_to_external_app_button'; +import { PolicyDetailsRouteState } from '../../../../../common/endpoint/types'; +import { getEndpointListPath } from '../../../common/routing'; +import { useAppUrl } from '../../../../common/lib/kibana'; +import { APP_ID } from '../../../../../common/constants'; export const PolicyDetails = React.memo(() => { // TODO: Remove this and related code when removing FF const isTrustedAppsByPolicyEnabled = useIsExperimentalFeatureEnabled( 'trustedAppsByPolicyEnabled' ); + const { state: routeState = {} } = useLocation(); + const { getAppUrl } = useAppUrl(); // Store values const policyItem = usePolicyDetailsSelector(policyDetails); @@ -31,6 +40,34 @@ export const PolicyDetails = React.memo(() => { const policyName = policyItem?.name ?? ''; const policyDescription = policyItem?.description ?? undefined; + const backLinkOptions = useMemo(() => { + if (routeState?.backLink) { + return { + onBackButtonNavigateTo: routeState.backLink.navigateTo, + backButtonLabel: routeState.backLink.label, + backButtonUrl: routeState.backLink.href, + }; + } + + const endpointListPath = getEndpointListPath({ name: 'endpointList' }); + + return { + backButtonLabel: i18n.translate( + 'xpack.securitySolution.endpoint.policy.details.backToListTitle', + { + defaultMessage: 'Back to endpoint hosts', + } + ), + backButtonUrl: getAppUrl({ path: endpointListPath }), + onBackButtonNavigateTo: [ + APP_ID, + { + path: endpointListPath, + }, + ], + }; + }, [getAppUrl, routeState?.backLink]); + const headerRightContent = ( { ); const backToEndpointList = ( - + ); return ( diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/selectors.ts b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/selectors.ts index 388d8b5e6ed66..1565dc1310b18 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/selectors.ts @@ -7,7 +7,12 @@ import { createSelector } from 'reselect'; import { ServerApiError } from '../../../../common/types'; -import { Immutable, NewTrustedApp, TrustedApp } from '../../../../../common/endpoint/types'; +import { + Immutable, + NewTrustedApp, + PolicyData, + TrustedApp, +} from '../../../../../common/endpoint/types'; import { MANAGEMENT_PAGE_SIZE_OPTIONS } from '../../../common/constants'; import { @@ -226,6 +231,18 @@ export const listOfPolicies: ( return isLoadedResourceState(policies) ? policies.data.items : []; }); +export const getMapOfPoliciesById: ( + state: Immutable +) => Immutable>> = createSelector( + listOfPolicies, + (policies) => { + return policies.reduce>>((mapById, policy) => { + mapById[policy.id] = policy; + return mapById; + }, {}) as Immutable>>; + } +); + export const isEdit: (state: Immutable) => boolean = createSelector( getCurrentLocation, ({ show }) => { diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/__snapshots__/index.test.tsx.snap deleted file mode 100644 index cbeea78f51040..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,249 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`trusted_app_card TrustedAppCard should render correctly 1`] = ` - - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - - Edit - - - Remove - - -`; - -exports[`trusted_app_card TrustedAppCard should trim long texts 1`] = ` - - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - - - Edit - - - Remove - - -`; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.stories.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.stories.tsx deleted file mode 100644 index e2e426caa1654..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.stories.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { ThemeProvider } from 'styled-components'; -import { storiesOf, addDecorator } from '@storybook/react'; -import { action } from '@storybook/addon-actions'; -import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; - -import { KibanaContextProvider } from '../../../../../../../../../../src/plugins/kibana_react/public'; -import { - ConditionEntryField, - TrustedApp, - WindowsConditionEntry, -} from '../../../../../../../common/endpoint/types'; - -import { createSampleTrustedApp } from '../../../test_utils'; - -import { TrustedAppCard } from '.'; - -addDecorator((storyFn) => ( - 'MMM D, YYYY @ HH:mm:ss.SSS' } }}> - ({ eui: euiLightVars, darkMode: false })}> - {storyFn()} - - -)); - -const PATH_CONDITION: WindowsConditionEntry = { - field: ConditionEntryField.PATH, - operator: 'included', - type: 'match', - value: '/some/path/on/file/system', -}; - -const SIGNER_CONDITION: WindowsConditionEntry = { - field: ConditionEntryField.SIGNER, - operator: 'included', - type: 'match', - value: 'Elastic', -}; - -storiesOf('TrustedApps/TrustedAppCard', module) - .add('default', () => { - const trustedApp: TrustedApp = createSampleTrustedApp(5); - trustedApp.created_at = '2020-09-17T14:52:33.899Z'; - trustedApp.entries = [PATH_CONDITION]; - - return ( - - ); - }) - .add('multiple entries', () => { - const trustedApp: TrustedApp = createSampleTrustedApp(5); - trustedApp.created_at = '2020-09-17T14:52:33.899Z'; - trustedApp.entries = [PATH_CONDITION, SIGNER_CONDITION]; - - return ( - - ); - }) - .add('longs texts', () => { - const trustedApp: TrustedApp = createSampleTrustedApp(5, true); - trustedApp.created_at = '2020-09-17T14:52:33.899Z'; - trustedApp.entries = [PATH_CONDITION, SIGNER_CONDITION]; - - return ( - - ); - }); diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.test.tsx deleted file mode 100644 index 0b1d8e0d7ac98..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { shallow } from 'enzyme'; -import React from 'react'; - -import { TrustedAppCard } from '.'; -import { createSampleTrustedApp } from '../../../test_utils'; - -describe('trusted_app_card', () => { - describe('TrustedAppCard', () => { - it('should render correctly', () => { - const element = shallow( - {}} - onEdit={() => {}} - /> - ); - - expect(element).toMatchSnapshot(); - }); - - it('should trim long texts', () => { - const element = shallow( - {}} - onEdit={() => {}} - /> - ); - - expect(element).toMatchSnapshot(); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.tsx deleted file mode 100644 index 419d8aaedfe03..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_app_card/index.tsx +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { memo, useCallback, useMemo } from 'react'; -import { isEmpty } from 'lodash/fp'; -import { EuiTableFieldDataColumnType } from '@elastic/eui'; - -import { - Immutable, - TrustedApp, - MacosLinuxConditionEntry, - WindowsConditionEntry, -} from '../../../../../../../common/endpoint/types'; - -import { FormattedDate } from '../../../../../../common/components/formatted_date'; -import { ConditionsTable } from '../../../../../../common/components/conditions_table'; -import { TextFieldValue } from '../../../../../../common/components/text_field_value'; -import { - ItemDetailsAction, - ItemDetailsCard, - ItemDetailsCardProps, - ItemDetailsPropertySummary, -} from '../../../../../../common/components/item_details_card'; - -import { - OS_TITLES, - PROPERTY_TITLES, - ENTRY_PROPERTY_TITLES, - CARD_DELETE_BUTTON_LABEL, - CONDITION_FIELD_TITLE, - OPERATOR_TITLES, - CARD_EDIT_BUTTON_LABEL, -} from '../../translations'; - -type Entry = MacosLinuxConditionEntry | WindowsConditionEntry; - -const getEntriesColumnDefinitions = (): Array> => [ - { - field: 'field', - name: ENTRY_PROPERTY_TITLES.field, - sortable: false, - truncateText: true, - textOnly: true, - width: '30%', - render(field: Entry['field'], _entry: Entry) { - return CONDITION_FIELD_TITLE[field]; - }, - }, - { - field: 'operator', - name: ENTRY_PROPERTY_TITLES.operator, - sortable: false, - truncateText: true, - width: '20%', - render(_field: Entry['operator'], entry: Entry) { - return entry.type === 'wildcard' ? OPERATOR_TITLES.matches : OPERATOR_TITLES.is; - }, - }, - { - field: 'value', - name: ENTRY_PROPERTY_TITLES.value, - sortable: false, - width: '60%', - 'data-test-subj': 'conditionValue', - render(field: Entry['value'], entry: Entry) { - return ( - - ); - }, - }, -]; - -export type TrustedAppCardProps = Pick & { - trustedApp: Immutable; - onDelete: (trustedApp: Immutable) => void; - onEdit: (trustedApp: Immutable) => void; -}; - -export const TrustedAppCard = memo( - ({ trustedApp, onDelete, onEdit, ...otherProps }) => { - const handleDelete = useCallback(() => onDelete(trustedApp), [onDelete, trustedApp]); - const handleEdit = useCallback(() => onEdit(trustedApp), [onEdit, trustedApp]); - - return ( - - - } - /> - } - /> - - } - /> - - } - /> - - } - /> - - } - /> - {!isEmpty(trustedApp.description) && ( - - } - /> - )} - - getEntriesColumnDefinitions(), [])} - items={useMemo(() => [...trustedApp.entries], [trustedApp.entries])} - badge="and" - className="trustedAppsConditionsTable" - responsive - /> - - - {CARD_EDIT_BUTTON_LABEL} - - - - {CARD_DELETE_BUTTON_LABEL} - - - ); - } -); - -TrustedAppCard.displayName = 'TrustedAppCard'; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap index 1355594831a24..3087914a438ef 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap @@ -372,35 +372,6 @@ exports[`TrustedAppsGrid renders correctly when failed loading data for the seco `; exports[`TrustedAppsGrid renders correctly when loaded data 1`] = ` -.c2 { - background-color: #f5f7fa; - padding: 16px; -} - -.c5 { - padding: 12px 24px 24px 0; -} - -.c5.c5.c5 { - margin-left: 0; -} - -.c5 .trustedAppsConditionsTable { - margin-left: 16px; -} - -.c3.c3.c3 { - width: 40%; - margin-top: 0; - margin-bottom: 8px; -} - -.c4.c4.c4 { - width: 60%; - margin-top: 0; - margin-bottom: 8px; -} - .c1 { position: relative; padding-top: 4px; @@ -414,6 +385,10 @@ exports[`TrustedAppsGrid renders correctly when loaded data 1`] = ` position: relative; } +.c3.artifactEntryCard + .c2.artifactEntryCard { + margin-top: 24px; +} + .c0 .trusted-app + .trusted-app { margin-top: 24px; } @@ -432,3194 +407,4074 @@ exports[`TrustedAppsGrid renders correctly when loaded data 1`] = ` class="body-content undefined" >
-
-
- Name -
-
- - +

trusted app 0 - - -

-
- OS -
-
- - - Windows - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
- - - someone - - -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - - someone - - -
-
- Description -
-
- +
+
- - Trusted App 0 - - - - -
-
-
-
-
-
+
+ +
+
+ class="euiText euiText--small" + > + Last updated +
+
+
+ class="euiText euiText--small" + > + + 1 minute ago + +
- - - - - - - - - - + + +
+
+
+ +
+
+
+
+
+ Created +
+
+
+
-
- - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
+ + 1 minute ago + +
+
+
+
+
+
+
+ +
+
+
+
+
+
-
- + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
-
- + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
+
+ +
+
+
+ Applied globally +
+
+
+
+
+
+
+

+ Trusted App 0 +

- -
+
-
-
- Name -
-
- - - trusted app 1 - - -
-
- OS -
-
- - - Mac - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
+ - - someone + + + + OS -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - someone + + IS - -
-
- Description -
-
- - - Trusted App 1 + + + Windows -
-
+ +
+
+ +
+
-
+
+

+ trusted app 1 +

+
+
-
+
+ +
+
+ class="euiText euiText--small" + > + Last updated +
+
+
+ class="euiText euiText--small" + > + + 1 minute ago + +
- - - - - - - - - - - - - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
-
-
-
-
-
-
-
- -
-
-
-
- +
+
+ Created +
+
+
+
+ + 1 minute ago + +
+
+
+
+
-
-
- -
-
-
-
-
- Name -
-
- - - trusted app 2 - - -
-
- OS -
-
- - - Linux - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
- - - someone - - -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - - someone - - -
-
- Description -
-
- - - Trusted App 2 - - -
-
+ +
+
+
-
+
+ + + + Created by + + + +
+
-
+
- +
+
+ someone
- - - - - - - - - - - - - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
-
-
-
- +
-
-
-
- + +
+
+
+
+ someone +
+
+
+
+
+
+ +
+
+
+ Applied globally +
+
+
+
+
+
+
+

+ Trusted App 1 +

-
-
+
-
-
- Name -
-
- - - trusted app 3 - - -
-
- OS -
-
- - - Windows - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
+ - - someone + + + + OS -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - someone + + IS - -
-
- Description -
-
- - - Trusted App 3 + + + macos -
-
+ +
+
+ +
+
-
+
+

+ trusted app 2 +

+
+
-
+
+ +
+
+ class="euiText euiText--small" + > + Last updated +
+
+
+ class="euiText euiText--small" + > + + 1 minute ago + +
- - - - - - - - - - + + +
+
+
+ +
+
+
+
+
+ Created +
+
+
+
-
- - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
+ + 1 minute ago + +
+
+
+
+
+
+
+ +
+
+
+
+
+
-
- +
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
-
- Name -
-
- - - trusted app 4 - - -
-
- OS -
-
- - - Mac - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
- - - someone - - -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - - someone - - -
-
- Description -
-
- - - Trusted App 4 - - -
-
-
-
-
-
-
-
-
-
-
+ +
+
+
-
-
-
-
+ someone
- - - - - - - - - - - - - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
-
-
-
- +
-
-
-
- + +
+
+
+
+ someone +
+
+
+
+
+
+ +
+
+
+ Applied globally +
+
+
+
+
+
+
+

+ Trusted App 2 +

- -
+
-
-
- Name -
-
- - - trusted app 5 - - -
-
- OS -
-
- - - Linux - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
+ - - someone + + + + OS -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - someone + + IS - -
-
- Description -
-
- - - Trusted App 5 + + + Linux -
-
+ +
+
+ +
+
-
+
+

+ trusted app 3 +

+
+
-
+
+ +
+
+ class="euiText euiText--small" + > + Last updated +
+
+
+ class="euiText euiText--small" + > + + 1 minute ago + +
- - - - - - - - - - + + +
+
+
+ +
+
+
+
+
+ Created +
+
+
+
-
- - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
+ + 1 minute ago + +
+
+
+
+
+
+
+ +
+
+
+
+
+
-
- + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
-
- +
-
-
-
-
-
-
- -
-
-
-
-
- Name -
-
- - - trusted app 6 - - -
-
- OS -
-
- - - Windows - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
- - - someone - - -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - - someone - - -
-
- Description -
-
- - - Trusted App 6 - - -
-
-
-
-
-
-
-
-
+
- +
+
+ someone
- - - - - - - - - - - - - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
+
+
+ +
+
-
- -
-
-
-
- -
+ Applied globally
+
+
+

+ Trusted App 3 +

+
-
-
+
-
-
- Name -
-
- - - trusted app 7 - - -
-
- OS -
-
- - - Mac - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
+ - - someone + + + + OS -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - someone + + IS - -
-
- Description -
-
- - - Trusted App 7 + + + Windows -
-
+ +
+
+
+
+
-
+
+

+ trusted app 4 +

+
+
-
+
+ +
+
+ class="euiText euiText--small" + > + Last updated +
+
+
+ class="euiText euiText--small" + > + + 1 minute ago + +
- - - - - - - - - - + + +
+
+
+ +
+
+
+
+
-
- - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
+ Created +
+
+
+
+ + 1 minute ago + +
+
+
+
+
+
+
+ +
+
+
+
+
+
-
- + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
-
- + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
-
-
-
-
-
-
-
-
- Name -
-
- - - trusted app 8 - - -
-
- OS -
-
- +
+
- - Linux - - - -
- Date created -
-
- 1 minute ago -
-
- Created by -
-
+
+ Applied globally +
+
+
+
+
+
+
+

+ Trusted App 4 +

+
+
+
+
+
+
+ - - someone + + + + OS - -
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - someone + + IS - -
-
- Description -
-
- - - Trusted App 8 + + + macos -
- +
+
+
+
+
+
-
+
+

+ trusted app 5 +

+
+
-
+
+ +
+
+ class="euiText euiText--small" + > + Last updated +
+
+
+ class="euiText euiText--small" + > + + 1 minute ago + +
- - - - - - - - - - + + +
+
+
+ +
+
+
+
+
+ Created +
+
+
+
-
- - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
+ + 1 minute ago + +
+
+
+
+
+
+
+ +
+
+
+
+
+
-
- + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
-
- + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
+
+ +
+
+
+ Applied globally +
+
+
+
+
+
+
+

+ Trusted App 5 +

-
-
+
-
-
- Name -
-
- - - trusted app 9 - - -
-
- OS -
-
- - - Windows - - -
-
- Date created -
-
- 1 minute ago -
-
- Created by -
-
+ - - someone + + + + OS -
-
- Date modified -
-
- 1 minute ago -
-
- Modified by -
-
- - someone + + IS - -
-
- Description -
-
- - - Trusted App 9 + + + Linux -
-
+ +
+
+ +
+
-
+
+

+ trusted app 6 +

+
+
-
+
+ +
+
+ class="euiText euiText--small" + > + Last updated +
+
+
+ class="euiText euiText--small" + > + + 1 minute ago + +
- - - - - - - - - - - - - -
-
- - - Field - - - - - - Operator - - - - - - Value - - -
-
- - No items found - -
-
-
-
-
-
-
-
-
- -
-
-
-
-
+
- - Remove - - - +
+
+ Created +
+
+
+
+ + 1 minute ago + +
+
+
+
+
+
+
+
+ +
+
+
-
- - - -
-
-
-
-
- +
+
+ + + + Created by + + + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
+
+
+
+
+ + + + Updated by + + + +
+
+
+
+
+ +
+
+
+
+ someone +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ Applied globally +
+
+
+
+
+
+
+

+ Trusted App 6 +

-
-
-
+
+ +
+
+
+
- - -
  • +
  • +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    - +
    +
    + + +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 7 +

    +
    +
    +
    +
    +
    +
    + + + - 5 + OS - - -
  • - … -
  • -
  • - -
  • - - - +
    +
    +
    +
    - - - - - -`; - -exports[`TrustedAppsGrid renders correctly when loading data for the first time 1`] = ` -.c1 { - position: relative; - padding-top: 4px; -} - -.c1 .body { - min-height: 40px; -} - -.c1 .body-content { - position: relative; -} - -.c0 .trusted-app + .trusted-app { - margin-top: 24px; -} - -
    -
    +
    +
    +
    +
    +
    +
    +

    + trusted app 8 +

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 8 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + Linux + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + trusted app 9 +

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 9 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + Windows + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +`; + +exports[`TrustedAppsGrid renders correctly when loading data for the first time 1`] = ` +.c1 { + position: relative; + padding-top: 4px; +} + +.c1 .body { + min-height: 40px; +} + +.c1 .body-content { + position: relative; +} + +.c0 .trusted-app + .trusted-app { + margin-top: 24px; +} + +
    +
    @@ -3639,35 +4494,6 @@ exports[`TrustedAppsGrid renders correctly when loading data for the first time `; exports[`TrustedAppsGrid renders correctly when loading data for the second time 1`] = ` -.c2 { - background-color: #f5f7fa; - padding: 16px; -} - -.c5 { - padding: 12px 24px 24px 0; -} - -.c5.c5.c5 { - margin-left: 0; -} - -.c5 .trustedAppsConditionsTable { - margin-left: 16px; -} - -.c3.c3.c3 { - width: 40%; - margin-top: 0; - margin-bottom: 8px; -} - -.c4.c4.c4 { - width: 60%; - margin-top: 0; - margin-bottom: 8px; -} - .c1 { position: relative; padding-top: 4px; @@ -3681,6 +4507,10 @@ exports[`TrustedAppsGrid renders correctly when loading data for the second time position: relative; } +.c3.artifactEntryCard + .c2.artifactEntryCard { + margin-top: 24px; +} + .c0 .trusted-app + .trusted-app { margin-top: 24px; } @@ -3702,6179 +4532,7914 @@ exports[`TrustedAppsGrid renders correctly when loading data for the second time class="body-content undefined" >
    +
    +
    +
    +
    +
    +

    + trusted app 0 +

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 0 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + Windows + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + trusted app 1 +

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 1 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + macos + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + trusted app 2 +

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 2 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + Linux + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + trusted app 3 +

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 3 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + Windows + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + trusted app 4 +

    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Created by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + Updated by + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 4 +

    +
    +
    +
    +
    -
    -
    - Name -
    -
    - - - trusted app 0 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 0 + + + macos -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 5 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - + + +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    -
    - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 5 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 1 - - -
    -
    - OS -
    -
    - - - Mac - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone - - -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    + - - someone + + + + OS -
    -
    - Description -
    -
    - - Trusted App 1 + + IS + + + + Linux -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 6 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    +
    - - Remove - - - +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    -
    -
    -
    -
    -
    -
    -
    -
    - Name -
    -
    - - - trusted app 2 - - -
    -
    - OS -
    -
    - - - Linux - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone - - -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - - someone - - -
    -
    - Description -
    -
    - - - Trusted App 2 - - -
    -
    + +
    +
    +
    -
    +
    + + + + Created by + + + +
    +
    -
    +
    - +
    +
    + someone
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    - +
    -
    -
    -
    - + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 6 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 3 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 3 + + + Windows -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 7 +

    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Created +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally
    +
    +
    +

    + Trusted App 7 +

    +
    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 4 - - -
    -
    - OS -
    -
    - - - Mac - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 4 + + + macos -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 8 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    +
    - - Remove - - - +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    -
    -
    -
    -
    -
    -
    -
    -
    - Name -
    -
    - - - trusted app 5 - - -
    -
    - OS -
    -
    - - - Linux - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone - - -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - - someone - - -
    -
    - Description -
    -
    - - - Trusted App 5 - - -
    -
    + +
    +
    +
    -
    +
    + + + + Created by + + + +
    +
    -
    +
    - +
    +
    + someone
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    - +
    -
    -
    -
    - + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 8 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 6 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 6 + + + Linux -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 9 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - + + +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    -
    - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 9 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + Windows + + + +
    +
    +
    +
    +
    +
    -
    -
    - Name -
    -
    + + Rows per page + : + 10 + + + +
    +
    +
    +
    +
    + + + + + +
    +
    +
    + + + +`; + +exports[`TrustedAppsGrid renders correctly when new page and page size set (not loading yet) 1`] = ` +.c1 { + position: relative; + padding-top: 4px; +} + +.c1 .body { + min-height: 40px; +} + +.c1 .body-content { + position: relative; +} + +.c3.artifactEntryCard + .c2.artifactEntryCard { + margin-top: 24px; +} + +.c0 .trusted-app + .trusted-app { + margin-top: 24px; +} + +
    +
    +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 0 +

    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Created +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 0 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 8 - - -
    -
    - OS -
    -
    - - - Linux - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 8 + + + Windows -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 1 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - + + +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    -
    - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 1 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 9 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 9 + + + macos -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 2 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - + + +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    -
    - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - +
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    +
    +
    +
    +
    +
    -
    +
    +
    - 3 - - - - -
  • +
  • +
    +
    +
    +
    +
    +

    -

    +
    +
    +
    +
    +
    + + + - 4 + OS - - -
  • - -
  • -
  • - … -
  • -
  • - -
  • - - - +
    +
    +
    +
    - - - - - -`; - -exports[`TrustedAppsGrid renders correctly when new page and page size set (not loading yet) 1`] = ` -.c2 { - background-color: #f5f7fa; - padding: 16px; -} - -.c5 { - padding: 12px 24px 24px 0; -} - -.c5.c5.c5 { - margin-left: 0; -} - -.c5 .trustedAppsConditionsTable { - margin-left: 16px; -} - -.c3.c3.c3 { - width: 40%; - margin-top: 0; - margin-bottom: 8px; -} - -.c4.c4.c4 { - width: 60%; - margin-top: 0; - margin-bottom: 8px; -} - -.c1 { - position: relative; - padding-top: 4px; -} - -.c1 .body { - min-height: 40px; -} - -.c1 .body-content { - position: relative; -} - -.c0 .trusted-app + .trusted-app { - margin-top: 24px; -} - -
    -
    -
    -
    -
    -
    -
    - Name -
    -
    - - - trusted app 0 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone - - -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - + trusted app 3 + +
    +
    - - someone - - - -
    - Description -
    -
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    - - - Trusted App 0 - - - - + +
    +
    +
    -
    +
    + + + + Created by + + + +
    +
    -
    +
    - +
    +
    + someone
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    - +
    -
    -
    -
    - + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 3 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 1 - - -
    -
    - OS -
    -
    - - - Mac - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 1 + + + Windows -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 4 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    +
    - - Remove - - - +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    -
    -
    -
    -
    -
    -
    -
    -
    - Name -
    -
    - - - trusted app 2 - - -
    -
    - OS -
    -
    - - - Linux - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone - - -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - - someone - - -
    -
    - Description -
    -
    - - - Trusted App 2 - - -
    -
    + +
    +
    +
    -
    +
    + + + + Created by + + + +
    +
    -
    +
    +
    + +
    +
    +
    -
    -
    -
    -
    + someone
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    - +
    -
    -
    -
    - + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 4 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 3 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 3 + + + macos -
    -
    + +
    +
    + +
    +
    -
    +
    +

    + trusted app 5 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - + + +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    -
    - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 5 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 4 - - -
    -
    - OS -
    -
    - - - Mac - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 4 + + + Linux -
    -
    + +
    +
    + +
    +
    -
    +
    +

    + trusted app 6 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    +
    - - Remove - - - +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    -
    -
    - -
    -
    -
    -
    -
    - Name -
    -
    - - - trusted app 5 - - -
    -
    - OS -
    -
    - - - Linux - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone - - -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - - someone - - -
    -
    - Description -
    -
    - - - Trusted App 5 - - -
    -
    + +
    +
    +
    -
    +
    + + + + Created by + + + +
    +
    -
    +
    - +
    +
    + someone
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    - +
    -
    -
    -
    - + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 6 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 6 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 6 + + + Windows -
    -
    + +
    +
    + +
    +
    -
    +
    +

    + trusted app 7 +

    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + Last updated +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Created +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 7 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 7 - - -
    -
    - OS -
    -
    + - - Mac - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 7 + + + macos -
    -
    + +
    +
    +
    +
    +
    -
    +
    +

    + trusted app 8 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    +
    - - Remove - - - +
    +
    + Created +
    +
    +
    +
    + + 1 minute ago + +
    +
    +
    +
    +
    -
    -
    -
    -
    -
    -
    -
    -
    - Name -
    -
    - - - trusted app 8 - - -
    -
    - OS -
    -
    - - - Linux - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    - - - someone - - -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - - someone - - -
    -
    - Description -
    -
    - - - Trusted App 8 - - -
    -
    + +
    +
    +
    -
    +
    + + + + Created by + + + +
    +
    -
    +
    - +
    +
    + someone
    - - - - - - - - - - - - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    -
    -
    -
    - +
    -
    -
    -
    - + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 8 +

    -
    -
    +
    -
    -
    - Name -
    -
    - - - trusted app 9 - - -
    -
    - OS -
    -
    - - - Windows - - -
    -
    - Date created -
    -
    - 1 minute ago -
    -
    - Created by -
    -
    + - - someone + + + + OS -
    -
    - Date modified -
    -
    - 1 minute ago -
    -
    - Modified by -
    -
    - - someone + + IS - -
    -
    - Description -
    -
    - - - Trusted App 9 + + + Linux -
    -
    + +
    +
    + +
    +
    -
    +
    +

    + trusted app 9 +

    +
    +
    -
    +
    + +
    +
    + class="euiText euiText--small" + > + Last updated +
    +
    +
    + class="euiText euiText--small" + > + + 1 minute ago + +
    - - - - - - - - - - + + +
    +
    +
    + +
    +
    +
    +
    +
    + Created +
    +
    +
    +
    -
    - - -
    -
    - - - Field - - - - - - Operator - - - - - - Value - - -
    -
    - - No items found - -
    -
    + + 1 minute ago + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    -
    - + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + someone +
    +
    +
    +
    +
    +
    + +
    +
    +
    + Applied globally +
    +
    +
    +
    +
    +
    +
    +

    + Trusted App 9 +

    +
    +
    +
    +
    +
    +
    + + + + + + OS + + + + + IS + + + + Windows + + + +
    diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.test.tsx index 74f3f0524b304..d5eca75f9c2b5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { render } from '@testing-library/react'; +import { render, act } from '@testing-library/react'; import React from 'react'; import { Provider } from 'react-redux'; @@ -18,7 +18,6 @@ import { createUserChangedUrlAction, createGlobalNoMiddlewareStore, } from '../../../test_utils'; - import { TrustedAppsGrid } from '.'; import { EuiThemeProvider } from '../../../../../../../../../../src/plugins/kibana_react/common'; @@ -26,6 +25,8 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ htmlIdGenerator: () => () => 'mockId', })); +jest.mock('../../../../../../common/lib/kibana'); + const now = 111111; const renderList = (store: ReturnType) => { @@ -129,7 +130,15 @@ describe('TrustedAppsGrid', () => { ); store.dispatch = jest.fn(); - (await renderList(store).findAllByTestId('trustedAppDeleteButton'))[0].click(); + const renderResult = renderList(store); + + await act(async () => { + (await renderResult.findAllByTestId('trustedAppCard-header-actions-button'))[0].click(); + }); + + await act(async () => { + (await renderResult.findByTestId('deleteTrustedAppAction')).click(); + }); expect(store.dispatch).toBeCalledWith({ type: 'trustedAppDeletionDialogStarted', diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.tsx index 8d8b52ac62358..ba09d0c7ee0cc 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/index.tsx @@ -5,10 +5,13 @@ * 2.0. */ -import React, { memo, useCallback } from 'react'; +import React, { memo, useCallback, useMemo } from 'react'; import { useHistory } from 'react-router-dom'; import styled from 'styled-components'; +import { i18n } from '@kbn/i18n'; +import { useDispatch } from 'react-redux'; +import { Dispatch } from 'redux'; import { Pagination } from '../../../state'; import { @@ -17,28 +20,31 @@ import { getListItems, getListPagination, isListLoading, + getMapOfPoliciesById, } from '../../../store/selectors'; -import { - useTrustedAppsNavigateCallback, - useTrustedAppsSelector, - useTrustedAppsStoreActionCallback, -} from '../../hooks'; +import { useTrustedAppsNavigateCallback, useTrustedAppsSelector } from '../../hooks'; -import { TrustedAppCard, TrustedAppCardProps } from '../trusted_app_card'; -import { getTrustedAppsListPath } from '../../../../../common/routing'; +import { getPolicyDetailPath, getTrustedAppsListPath } from '../../../../../common/routing'; import { PaginatedContent, PaginatedContentProps, } from '../../../../../components/paginated_content'; -import { TrustedApp } from '../../../../../../../common/endpoint/types'; +import { PolicyDetailsRouteState, TrustedApp } from '../../../../../../../common/endpoint/types'; +import { + ArtifactEntryCard, + ArtifactEntryCardProps, +} from '../../../../../components/artifact_entry_card'; +import { AppAction } from '../../../../../../common/store/actions'; +import { APP_ID } from '../../../../../../../common/constants'; +import { useAppUrl } from '../../../../../../common/lib/kibana'; export interface PaginationBarProps { pagination: Pagination; onChange: (pagination: { size: number; index: number }) => void; } -type TrustedAppCardType = typeof TrustedAppCard; +type ArtifactEntryCardType = typeof ArtifactEntryCard; const RootWrapper = styled.div` .trusted-app + .trusted-app { @@ -46,52 +52,140 @@ const RootWrapper = styled.div` } `; +const BACK_TO_TRUSTED_APPS_LABEL = i18n.translate( + 'xpack.securitySolution.trustedapps.grid.policyDetailsLinkBackLabel', + { defaultMessage: 'Back to trusted Applications' } +); + +const EDIT_TRUSTED_APP_ACTION_LABEL = i18n.translate( + 'xpack.securitySolution.trustedapps.grid.cardAction.edit', + { + defaultMessage: 'Edit trusted application', + } +); + +const DELETE_TRUSTED_APP_ACTION_LABEL = i18n.translate( + 'xpack.securitySolution.trustedapps.grid.cardAction.delete', + { + defaultMessage: 'Delete trusted application', + } +); + export const TrustedAppsGrid = memo(() => { const history = useHistory(); + const dispatch = useDispatch>(); + const { getAppUrl } = useAppUrl(); + const pagination = useTrustedAppsSelector(getListPagination); const listItems = useTrustedAppsSelector(getListItems); const isLoading = useTrustedAppsSelector(isListLoading); const error = useTrustedAppsSelector(getListErrorMessage); const location = useTrustedAppsSelector(getCurrentLocation); - - const handleTrustedAppDelete = useTrustedAppsStoreActionCallback((trustedApp) => ({ - type: 'trustedAppDeletionDialogStarted', - payload: { entry: trustedApp }, - })); - - const handleTrustedAppEdit: TrustedAppCardProps['onEdit'] = useCallback( - (trustedApp) => { - history.push( - getTrustedAppsListPath({ - ...location, - show: 'edit', - id: trustedApp.id, - }) - ); - }, - [history, location] - ); + const policyListById = useTrustedAppsSelector(getMapOfPoliciesById); const handlePaginationChange: PaginatedContentProps< TrustedApp, - TrustedAppCardType + ArtifactEntryCardType >['onChange'] = useTrustedAppsNavigateCallback(({ pageIndex, pageSize }) => ({ page_index: pageIndex, page_size: pageSize, })); + const artifactCardPropsPerItem = useMemo(() => { + const cachedCardProps: Record = {}; + + // Casting `listItems` below to remove the `Immutable<>` from it in order to prevent errors + // with common component's props + for (const trustedApp of listItems as TrustedApp[]) { + let policies: ArtifactEntryCardProps['policies']; + + if (trustedApp.effectScope.type === 'policy' && trustedApp.effectScope.policies.length) { + policies = trustedApp.effectScope.policies.reduce< + Required['policies'] + >((policyToNavOptionsMap, policyId) => { + const currentPagePath = getTrustedAppsListPath({ + ...location, + }); + + const policyDetailsPath = getPolicyDetailPath(policyId); + + const routeState: PolicyDetailsRouteState = { + backLink: { + label: BACK_TO_TRUSTED_APPS_LABEL, + navigateTo: [ + APP_ID, + { + path: currentPagePath, + }, + ], + href: getAppUrl({ path: currentPagePath }), + }, + }; + + policyToNavOptionsMap[policyId] = { + navigateAppId: APP_ID, + navigateOptions: { + path: policyDetailsPath, + state: routeState, + }, + href: getAppUrl({ path: policyDetailsPath }), + children: policyListById[policyId]?.name ?? policyId, + }; + return policyToNavOptionsMap; + }, {}); + } + + cachedCardProps[trustedApp.id] = { + item: trustedApp, + policies, + 'data-test-subj': 'trustedAppCard', + actions: [ + { + icon: 'controlsHorizontal', + onClick: () => { + history.push( + getTrustedAppsListPath({ + ...location, + show: 'edit', + id: trustedApp.id, + }) + ); + }, + 'data-test-subj': 'editTrustedAppAction', + children: EDIT_TRUSTED_APP_ACTION_LABEL, + }, + { + icon: 'trash', + onClick: () => { + dispatch({ + type: 'trustedAppDeletionDialogStarted', + payload: { entry: trustedApp }, + }); + }, + 'data-test-subj': 'deleteTrustedAppAction', + children: DELETE_TRUSTED_APP_ACTION_LABEL, + }, + ], + }; + } + + return cachedCardProps; + }, [dispatch, getAppUrl, history, listItems, location, policyListById]); + + const handleArtifactCardProps = useCallback( + (trustedApp: TrustedApp) => { + return artifactCardPropsPerItem[trustedApp.id]; + }, + [artifactCardPropsPerItem] + ); + return ( - + items={listItems as TrustedApp[]} onChange={handlePaginationChange} - ItemComponent={TrustedAppCard} - itemComponentProps={(ta) => ({ - trustedApp: ta, - onDelete: handleTrustedAppDelete, - onEdit: handleTrustedAppEdit, - className: 'trusted-app', - })} + ItemComponent={ArtifactEntryCard} + itemComponentProps={handleArtifactCardProps} loading={isLoading} itemId="id" error={error} diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts index 9e2cad93fc51f..6ffcf5614a697 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/translations.ts @@ -7,7 +7,6 @@ import { i18n } from '@kbn/i18n'; import { - TrustedApp, MacosLinuxConditionEntry, WindowsConditionEntry, ConditionEntryField, @@ -61,35 +60,6 @@ export const OPERATOR_TITLES: { [K in OperatorFieldIds]: string } = { }), }; -export const PROPERTY_TITLES: Readonly< - { [K in keyof Omit]: string } -> = { - name: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.name', { - defaultMessage: 'Name', - }), - os: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.os', { - defaultMessage: 'OS', - }), - created_at: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.createdAt', { - defaultMessage: 'Date created', - }), - created_by: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.createdBy', { - defaultMessage: 'Created by', - }), - updated_at: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.updatedAt', { - defaultMessage: 'Date modified', - }), - updated_by: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.updatedBy', { - defaultMessage: 'Modified by', - }), - description: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.description', { - defaultMessage: 'Description', - }), - effectScope: i18n.translate('xpack.securitySolution.trustedapps.trustedapp.effectScope', { - defaultMessage: 'Effect scope', - }), -}; - export const ENTRY_PROPERTY_TITLES: Readonly< { [K in keyof Omit]: string } > = { @@ -104,41 +74,6 @@ export const ENTRY_PROPERTY_TITLES: Readonly< }), }; -export const ACTIONS_COLUMN_TITLE = i18n.translate( - 'xpack.securitySolution.trustedapps.list.columns.actions', - { - defaultMessage: 'Actions', - } -); - -export const LIST_ACTIONS = { - delete: { - name: i18n.translate('xpack.securitySolution.trustedapps.list.actions.delete', { - defaultMessage: 'Remove', - }), - description: i18n.translate( - 'xpack.securitySolution.trustedapps.list.actions.delete.description', - { - defaultMessage: 'Remove this entry', - } - ), - }, -}; - -export const CARD_DELETE_BUTTON_LABEL = i18n.translate( - 'xpack.securitySolution.trustedapps.card.removeButtonLabel', - { - defaultMessage: 'Remove', - } -); - -export const CARD_EDIT_BUTTON_LABEL = i18n.translate( - 'xpack.securitySolution.trustedapps.card.editButtonLabel', - { - defaultMessage: 'Edit', - } -); - export const GRID_VIEW_TOGGLE_LABEL = i18n.translate( 'xpack.securitySolution.trustedapps.view.toggle.grid', { diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx index ff7ba8068b4ff..30e170575e2f4 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx @@ -183,8 +183,13 @@ describe('When on the Trusted Apps Page', () => { beforeEach(async () => { renderResult = await renderWithListData(); + + await act(async () => { + (await renderResult.findAllByTestId('trustedAppCard-header-actions-button'))[0].click(); + }); + act(() => { - fireEvent.click(renderResult.getByTestId('trustedAppEditButton')); + fireEvent.click(renderResult.getByTestId('editTrustedAppAction')); }); }); diff --git a/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts index bfa3fe88f7ac8..3fb05c8bf1048 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts @@ -11,10 +11,14 @@ import { KbnClient } from '@kbn/test'; import bluebird from 'bluebird'; import { basename } from 'path'; import { TRUSTED_APPS_CREATE_API, TRUSTED_APPS_LIST_API } from '../../../common/endpoint/constants'; -import { NewTrustedApp, OperatingSystem, TrustedApp } from '../../../common/endpoint/types'; +import { TrustedApp } from '../../../common/endpoint/types'; +import { TrustedAppGenerator } from '../../../common/endpoint/data_generators/trusted_app_generator'; +import { indexFleetEndpointPolicy } from '../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { setupFleetForEndpoint } from '../../../common/endpoint/data_loaders/setup_fleet_for_endpoint'; const defaultLogger = new ToolingLog({ level: 'info', writeTo: process.stdout }); const separator = '----------------------------------------'; +const trustedAppGenerator = new TrustedAppGenerator(); export const cli = async () => { const cliDefaults = { @@ -67,106 +71,62 @@ export const run: (options?: RunOptions) => Promise = async ({ }); // touch the Trusted Apps List so it can be created - await kbnClient.request({ - method: 'GET', - path: TRUSTED_APPS_LIST_API, - }); + // and + // setup fleet with endpoint integrations + logger.info('setting up Fleet with endpoint and creating trusted apps list'); + const [installedEndpointPackage] = await Promise.all([ + setupFleetForEndpoint(kbnClient).then((response) => response.endpointPackage), + + kbnClient.request({ + method: 'GET', + path: TRUSTED_APPS_LIST_API, + }), + ]); + + // Setup a list of read endpoint policies and return a method to randomly select one + const randomPolicyId: () => string = await (async () => { + const randomN = (max: number): number => Math.floor(Math.random() * max); + const policyIds: string[] = []; + + for (let i = 0, t = 5; i < t; i++) { + policyIds.push( + ( + await indexFleetEndpointPolicy( + kbnClient, + `Policy for Trusted App assignment ${i + 1}`, + installedEndpointPackage.version + ) + ).integrationPolicies[0].id + ); + } + + return () => policyIds[randomN(policyIds.length)]; + })(); return bluebird.map( Array.from({ length: count }), - () => - kbnClient + async () => { + const body = trustedAppGenerator.generateTrustedAppForCreate(); + + if (body.effectScope.type === 'policy') { + body.effectScope.policies = [randomPolicyId(), randomPolicyId()]; + } + + return kbnClient .request({ method: 'POST', path: TRUSTED_APPS_CREATE_API, - body: generateTrustedAppEntry(), + body, }) .then(({ data }) => { logger.write(data.id); return data; - }), + }); + }, { concurrency: 10 } ); }; -interface GenerateTrustedAppEntryOptions { - os?: OperatingSystem; - name?: string; -} -const generateTrustedAppEntry: (options?: GenerateTrustedAppEntryOptions) => object = ({ - os = randomOperatingSystem(), - name = randomName(), -} = {}): NewTrustedApp => { - const newTrustedApp: NewTrustedApp = { - description: `Generator says we trust ${name}`, - name, - os, - effectScope: { - type: 'global', - }, - entries: [ - { - // @ts-ignore - field: 'process.hash.*', - operator: 'included', - type: 'match', - value: '1234234659af249ddf3e40864e9fb241', - }, - { - // @ts-ignore - field: 'process.executable.caseless', - operator: 'included', - type: 'match', - value: '/one/two/three', - }, - ], - }; - - return newTrustedApp; -}; - -const randomN = (max: number): number => Math.floor(Math.random() * max); - -const randomName = (() => { - const names = [ - 'Symantec Endpoint Security', - 'Bitdefender GravityZone', - 'Malwarebytes', - 'Sophos Intercept X', - 'Webroot Business Endpoint Protection', - 'ESET Endpoint Security', - 'FortiClient', - 'Kaspersky Endpoint Security', - 'Trend Micro Apex One', - 'CylancePROTECT', - 'VIPRE', - 'Norton', - 'McAfee Endpoint Security', - 'AVG AntiVirus', - 'CrowdStrike Falcon', - 'Avast Business Antivirus', - 'Avira Antivirus', - 'Cisco AMP for Endpoints', - 'Eset Endpoint Antivirus', - 'VMware Carbon Black', - 'Palo Alto Networks Traps', - 'Trend Micro', - 'SentinelOne', - 'Panda Security for Desktops', - 'Microsoft Defender ATP', - ]; - const count = names.length; - - return () => names[randomN(count)]; -})(); - -const randomOperatingSystem = (() => { - const osKeys = Object.keys(OperatingSystem) as Array; - const count = osKeys.length; - - return () => OperatingSystem[osKeys[randomN(count)]]; -})(); - const createRunLogger = () => { let groupCount = 1; let itemCount = 0; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index aa9ea1a9b5b76..c71980f14d428 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -23536,10 +23536,8 @@ "xpack.securitySolution.topN.closeButtonLabel": "閉じる", "xpack.securitySolution.topN.rawEventsSelectLabel": "未加工イベント", "xpack.securitySolution.trustedapps.aboutInfo": "パフォーマンスを改善したり、ホストで実行されている他のアプリケーションとの競合を解消したりするには、信頼できるアプリケーションを追加します。", - "xpack.securitySolution.trustedapps.card.editButtonLabel": "編集", "xpack.securitySolution.trustedapps.card.operator.is": "is", "xpack.securitySolution.trustedapps.card.operator.matches": "一致", - "xpack.securitySolution.trustedapps.card.removeButtonLabel": "削除", "xpack.securitySolution.trustedapps.create.conditionFieldInvalidHashMsg": "[{row}] 無効なハッシュ値", "xpack.securitySolution.trustedapps.create.conditionFieldInvalidPathMsg": "[{row}] パスの形式が正しくありません。値を検証してください", "xpack.securitySolution.trustedapps.create.conditionFieldValueRequiredMsg": "[{row}] フィールドエントリには値が必要です", @@ -23567,10 +23565,7 @@ "xpack.securitySolution.trustedapps.deletionError.title": "削除失敗", "xpack.securitySolution.trustedapps.deletionSuccess.text": "「{name}」は信頼できるアプリケーションリストから削除されました。", "xpack.securitySolution.trustedapps.deletionSuccess.title": "正常に削除されました", - "xpack.securitySolution.trustedapps.list.actions.delete": "削除", - "xpack.securitySolution.trustedapps.list.actions.delete.description": "このエントリを削除", "xpack.securitySolution.trustedapps.list.addButton": "信頼できるアプリケーションを追加", - "xpack.securitySolution.trustedapps.list.columns.actions": "アクション", "xpack.securitySolution.trustedapps.list.pageTitle": "信頼できるアプリケーション", "xpack.securitySolution.trustedapps.list.search.placeholder": "次のフィールドで検索:名前、説明、値", "xpack.securitySolution.trustedapps.listEmptyState.message": "現在、エンドポイントには信頼できるアプリケーションがありません。", @@ -23593,18 +23588,9 @@ "xpack.securitySolution.trustedapps.middleware.editIdMissing": "IDが指定されていません", "xpack.securitySolution.trustedapps.policySelect.globalSectionTitle": "割り当て", "xpack.securitySolution.trustedapps.policySelect.globalSwitchTitle": "信頼できるアプリケーションをグローバルに適用", - "xpack.securitySolution.trustedapps.trustedapp.createdAt": "日付が作成されました", - "xpack.securitySolution.trustedapps.trustedapp.createdBy": "作成者", - "xpack.securitySolution.trustedapps.trustedapp.description": "説明", - "xpack.securitySolution.trustedapps.trustedapp.effectScope": "効果範囲", "xpack.securitySolution.trustedapps.trustedapp.entry.field": "フィールド", "xpack.securitySolution.trustedapps.trustedapp.entry.operator": "演算子", "xpack.securitySolution.trustedapps.trustedapp.entry.value": "値", - "xpack.securitySolution.trustedapps.trustedapp.name": "名前", - "xpack.securitySolution.trustedapps.trustedapp.os": "OS", - "xpack.securitySolution.trustedapps.trustedapp.updatedAt": "変更日", - "xpack.securitySolution.trustedapps.trustedapp.updatedBy": "変更者:", - "xpack.securitySolution.trustedapps.updateSuccess.title": "成功!", "xpack.securitySolution.trustedapps.view.toggle.grid": "グリッドビュー", "xpack.securitySolution.trustedapps.view.toggle.list": "リストビュー", "xpack.securitySolution.trustedapps.viewTypeToggle.controlLegend": "ビュータイプ", @@ -27089,4 +27075,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 24f1d07049840..ae2793d56ca9b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -23917,10 +23917,8 @@ "xpack.securitySolution.topN.closeButtonLabel": "关闭", "xpack.securitySolution.topN.rawEventsSelectLabel": "原始事件", "xpack.securitySolution.trustedapps.aboutInfo": "添加受信任的应用程序,以提高性能或缓解与主机上运行的其他应用程序的冲突。", - "xpack.securitySolution.trustedapps.card.editButtonLabel": "编辑", "xpack.securitySolution.trustedapps.card.operator.is": "是", "xpack.securitySolution.trustedapps.card.operator.matches": "匹配", - "xpack.securitySolution.trustedapps.card.removeButtonLabel": "移除", "xpack.securitySolution.trustedapps.create.conditionFieldInvalidHashMsg": "[{row}] 无效的哈希值", "xpack.securitySolution.trustedapps.create.conditionFieldInvalidPathMsg": "[{row}] 路径的格式可能不正确;请验证值", "xpack.securitySolution.trustedapps.create.conditionFieldValueRequiredMsg": "[{row}] 字段条目必须包含值", @@ -23948,10 +23946,7 @@ "xpack.securitySolution.trustedapps.deletionError.title": "移除失败", "xpack.securitySolution.trustedapps.deletionSuccess.text": "“{name}”已从受信任的应用程序列表中移除。", "xpack.securitySolution.trustedapps.deletionSuccess.title": "已成功移除", - "xpack.securitySolution.trustedapps.list.actions.delete": "移除", - "xpack.securitySolution.trustedapps.list.actions.delete.description": "移除此条目", "xpack.securitySolution.trustedapps.list.addButton": "添加受信任的应用程序", - "xpack.securitySolution.trustedapps.list.columns.actions": "操作", "xpack.securitySolution.trustedapps.list.pageTitle": "受信任的应用程序", "xpack.securitySolution.trustedapps.list.search.placeholder": "搜索下面的字段:name、description、value", "xpack.securitySolution.trustedapps.list.totalCount": "正在显示 {totalItemsCount, plural, other {# 个受信任的应用程序}}", @@ -23975,18 +23970,9 @@ "xpack.securitySolution.trustedapps.middleware.editIdMissing": "未提供 ID", "xpack.securitySolution.trustedapps.policySelect.globalSectionTitle": "分配", "xpack.securitySolution.trustedapps.policySelect.globalSwitchTitle": "全局应用受信任的应用程序", - "xpack.securitySolution.trustedapps.trustedapp.createdAt": "创建日期", - "xpack.securitySolution.trustedapps.trustedapp.createdBy": "创建者", - "xpack.securitySolution.trustedapps.trustedapp.description": "描述", - "xpack.securitySolution.trustedapps.trustedapp.effectScope": "作用范围", "xpack.securitySolution.trustedapps.trustedapp.entry.field": "字段", "xpack.securitySolution.trustedapps.trustedapp.entry.operator": "运算符", "xpack.securitySolution.trustedapps.trustedapp.entry.value": "值", - "xpack.securitySolution.trustedapps.trustedapp.name": "名称", - "xpack.securitySolution.trustedapps.trustedapp.os": "OS", - "xpack.securitySolution.trustedapps.trustedapp.updatedAt": "修改日期", - "xpack.securitySolution.trustedapps.trustedapp.updatedBy": "修改者", - "xpack.securitySolution.trustedapps.updateSuccess.title": "成功!", "xpack.securitySolution.trustedapps.view.toggle.grid": "网格视图", "xpack.securitySolution.trustedapps.view.toggle.list": "列表视图", "xpack.securitySolution.trustedapps.viewTypeToggle.controlLegend": "视图类型", @@ -27535,4 +27521,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} \ No newline at end of file +} diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts index 95fd914d32b07..684df902bb499 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts @@ -37,14 +37,20 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { SHA256 ); await testSubjects.click('addTrustedAppFlyout-createButton'); - expect(await testSubjects.getVisibleText('conditionValue')).to.equal(SHA256.toLowerCase()); + expect( + await testSubjects.getVisibleText('trustedAppCard-criteriaConditions-condition') + ).to.equal( + 'AND process.hash.*IS a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476' + ); await pageObjects.common.closeToast(); // Remove it - await testSubjects.click('trustedAppDeleteButton'); + await pageObjects.trustedApps.clickCardActionMenu(); + await testSubjects.click('deleteTrustedAppAction'); await testSubjects.click('trustedAppDeletionConfirm'); await testSubjects.waitForDeleted('trustedAppDeletionConfirm'); - expect(await testSubjects.existOrFail('trustedAppEmptyState')); + // We only expect one trusted app to have been visible + await testSubjects.missingOrFail('trustedAppCard'); }); }); }; diff --git a/x-pack/test/security_solution_endpoint/page_objects/trusted_apps_page.ts b/x-pack/test/security_solution_endpoint/page_objects/trusted_apps_page.ts index e32fa5e738f89..1678358acc11e 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/trusted_apps_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/trusted_apps_page.ts @@ -35,5 +35,13 @@ export function TrustedAppsPageProvider({ getService, getPageObjects }: FtrProvi await this.ensureIsOnTrustedAppsListPage(); return testSubjects.find('backToOrigin'); }, + + /** + * Clicks on the actions menu icon in the (only one) truated app card to show the popup with list of actions + */ + async clickCardActionMenu() { + await this.ensureIsOnTrustedAppsListPage(); + await testSubjects.click('trustedAppCard-header-actions-button'); + }, }; } diff --git a/x-pack/test/security_solution_endpoint/services/endpoint.ts b/x-pack/test/security_solution_endpoint/services/endpoint.ts index ae9e714315289..4b5b8d0717889 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint.ts @@ -189,7 +189,9 @@ export class EndpointTestResources extends FtrService { * installs (or upgrades) the Endpoint Fleet package * (NOTE: ensure that fleet is setup first before calling this function) */ - async installOrUpgradeEndpointFleetPackage(): Promise { + async installOrUpgradeEndpointFleetPackage(): ReturnType< + typeof installOrUpgradeEndpointFleetPackage + > { return installOrUpgradeEndpointFleetPackage(this.kbnClient); } } From 5763a2f25ae7ad5f307944c205167b55d8c94628 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 9 Sep 2021 18:31:46 -0500 Subject: [PATCH 28/32] [config] Remove deprecated environment variables `CONFIG_PATH` and `DATA_PATH` (#111535) --- docs/CHANGELOG.asciidoc | 12 +++++++ packages/kbn-utils/src/path/index.ts | 7 +--- .../deprecation/core_deprecations.test.ts | 36 ------------------- .../config/deprecation/core_deprecations.ts | 26 -------------- 4 files changed, 13 insertions(+), 68 deletions(-) diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index 96a7e57ef3e4f..5c409e22b9912 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -231,6 +231,18 @@ The `logging.useUTC` setting has been removed. For more information, refer to {k The default timezone is UTC. To change the timezone, set `logging.timezone: false` in kibana.yml. Change the timezone when the system, such as a docker container, is configured for a nonlocal timezone. ==== +[discrete] +[[breaking-32049]] +.Removed environment variables `CONFIG_PATH` and `DATA_PATH` +[%collapsible] +==== +*Details* + +The environment variables `CONFIG_PATH` and `DATA_PATH` have been removed. For more information, refer to {kibana-pull}32049[#32049] + +*Impact* + +Use the environment variable `KBN_PATH_CONF` instead of `CONFIG_PATH`. Use the setting `path.data` instead of `DATA_PATH`. +==== + // end::notable-breaking-changes[] [float] diff --git a/packages/kbn-utils/src/path/index.ts b/packages/kbn-utils/src/path/index.ts index 9d371a0c334a9..9ee699c22c30c 100644 --- a/packages/kbn-utils/src/path/index.ts +++ b/packages/kbn-utils/src/path/index.ts @@ -16,7 +16,6 @@ const isString = (v: any): v is string => typeof v === 'string'; const CONFIG_PATHS = [ process.env.KBN_PATH_CONF && join(process.env.KBN_PATH_CONF, 'kibana.yml'), process.env.KIBANA_PATH_CONF && join(process.env.KIBANA_PATH_CONF, 'kibana.yml'), // deprecated - process.env.CONFIG_PATH, // deprecated join(REPO_ROOT, 'config/kibana.yml'), '/etc/kibana/kibana.yml', ].filter(isString); @@ -28,11 +27,7 @@ const CONFIG_DIRECTORIES = [ '/etc/kibana', ].filter(isString); -const DATA_PATHS = [ - process.env.DATA_PATH, // deprecated - join(REPO_ROOT, 'data'), - '/var/lib/kibana', -].filter(isString); +const DATA_PATHS = [join(REPO_ROOT, 'data'), '/var/lib/kibana'].filter(isString); function findFile(paths: string[]) { const availablePath = paths.find((configPath) => { diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index a3bc9ee669903..d3a4d7f997062 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -18,24 +18,6 @@ describe('core deprecations', () => { process.env = { ...initialEnv }; }); - describe('configPath', () => { - it('logs a warning if CONFIG_PATH environ variable is set', () => { - process.env.CONFIG_PATH = 'somepath'; - const { messages } = applyCoreDeprecations(); - expect(messages).toMatchInlineSnapshot(` - Array [ - "Environment variable \\"CONFIG_PATH\\" is deprecated. It has been replaced with \\"KBN_PATH_CONF\\" pointing to a config folder", - ] - `); - }); - - it('does not log a warning if CONFIG_PATH environ variable is unset', () => { - delete process.env.CONFIG_PATH; - const { messages } = applyCoreDeprecations(); - expect(messages).toHaveLength(0); - }); - }); - describe('kibanaPathConf', () => { it('logs a warning if KIBANA_PATH_CONF environ variable is set', () => { process.env.KIBANA_PATH_CONF = 'somepath'; @@ -54,24 +36,6 @@ describe('core deprecations', () => { }); }); - describe('dataPath', () => { - it('logs a warning if DATA_PATH environ variable is set', () => { - process.env.DATA_PATH = 'somepath'; - const { messages } = applyCoreDeprecations(); - expect(messages).toMatchInlineSnapshot(` - Array [ - "Environment variable \\"DATA_PATH\\" will be removed. It has been replaced with kibana.yml setting \\"path.data\\"", - ] - `); - }); - - it('does not log a warning if DATA_PATH environ variable is unset', () => { - delete process.env.DATA_PATH; - const { messages } = applyCoreDeprecations(); - expect(messages).toHaveLength(0); - }); - }); - describe('xsrfDeprecation', () => { it('logs a warning if server.xsrf.whitelist is set', () => { const { migrated, messages } = applyCoreDeprecations({ diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 70c987e156448..a929a937988e8 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -21,30 +21,6 @@ const kibanaPathConf: ConfigDeprecation = (settings, fromPath, addDeprecation) = } }; -const configPathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (process.env?.CONFIG_PATH) { - addDeprecation({ - message: `Environment variable "CONFIG_PATH" is deprecated. It has been replaced with "KBN_PATH_CONF" pointing to a config folder`, - correctiveActions: { - manualSteps: ['Use "KBN_PATH_CONF" instead of "CONFIG_PATH" to point to a config folder.'], - }, - }); - } -}; - -const dataPathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (process.env?.DATA_PATH) { - addDeprecation({ - message: `Environment variable "DATA_PATH" will be removed. It has been replaced with kibana.yml setting "path.data"`, - correctiveActions: { - manualSteps: [ - `Set 'path.data' in the config file or CLI flag with the value of the environment variable "DATA_PATH".`, - ], - }, - }); - } -}; - const rewriteBasePathDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { if (settings.server?.basePath && !settings.server?.rewriteBasePath) { addDeprecation({ @@ -404,9 +380,7 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unu rename('cpuacct.cgroup.path.override', 'ops.cGroupOverrides.cpuAcctPath'), rename('server.xsrf.whitelist', 'server.xsrf.allowlist'), rewriteCorsSettings, - configPathDeprecation, kibanaPathConf, - dataPathDeprecation, rewriteBasePathDeprecation, cspRulesDeprecation, opsLoggingEventDeprecation, From 163fa7d2e036cfa5db2e1015e35e779396bf3ca1 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 9 Sep 2021 20:40:09 -0500 Subject: [PATCH 29/32] [build] Add cloud docker images (#107949) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Przemysław Hejman Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .gitignore | 1 + src/dev/build/args.test.ts | 7 +++ src/dev/build/args.ts | 2 + src/dev/build/build_distributables.ts | 6 +++ .../os_packages/create_os_package_tasks.ts | 24 +++++++++ .../tasks/os_packages/docker_generator/run.ts | 54 +++++++++++-------- .../docker_generator/template_context.ts | 3 ++ .../templates/base/Dockerfile | 31 +++++++++-- 8 files changed, 103 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 4f77a6e450c4b..32c77b20ef204 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /.chromium .DS_Store .node_binaries +/.beats .native_modules node_modules !/src/dev/npm/integration_tests/__fixtures__/fixture1/node_modules diff --git a/src/dev/build/args.test.ts b/src/dev/build/args.test.ts index d3ff822f9a3a3..64d89a650e62e 100644 --- a/src/dev/build/args.test.ts +++ b/src/dev/build/args.test.ts @@ -29,6 +29,7 @@ it('build default and oss dist for current platform, without packages, by defaul "createArchives": true, "createDebPackage": false, "createDockerCentOS": false, + "createDockerCloud": false, "createDockerContexts": true, "createDockerUBI": false, "createExamplePlugins": false, @@ -55,6 +56,7 @@ it('builds packages if --all-platforms is passed', () => { "createArchives": true, "createDebPackage": true, "createDockerCentOS": true, + "createDockerCloud": false, "createDockerContexts": true, "createDockerUBI": true, "createExamplePlugins": false, @@ -81,6 +83,7 @@ it('limits packages if --rpm passed with --all-platforms', () => { "createArchives": true, "createDebPackage": false, "createDockerCentOS": false, + "createDockerCloud": false, "createDockerContexts": true, "createDockerUBI": false, "createExamplePlugins": false, @@ -107,6 +110,7 @@ it('limits packages if --deb passed with --all-platforms', () => { "createArchives": true, "createDebPackage": true, "createDockerCentOS": false, + "createDockerCloud": false, "createDockerContexts": true, "createDockerUBI": false, "createExamplePlugins": false, @@ -134,6 +138,7 @@ it('limits packages if --docker passed with --all-platforms', () => { "createArchives": true, "createDebPackage": false, "createDockerCentOS": true, + "createDockerCloud": false, "createDockerContexts": true, "createDockerUBI": true, "createExamplePlugins": false, @@ -168,6 +173,7 @@ it('limits packages if --docker passed with --skip-docker-ubi and --all-platform "createArchives": true, "createDebPackage": false, "createDockerCentOS": true, + "createDockerCloud": false, "createDockerContexts": true, "createDockerUBI": false, "createExamplePlugins": false, @@ -195,6 +201,7 @@ it('limits packages if --all-platforms passed with --skip-docker-centos', () => "createArchives": true, "createDebPackage": true, "createDockerCentOS": false, + "createDockerCloud": false, "createDockerContexts": true, "createDockerUBI": true, "createExamplePlugins": false, diff --git a/src/dev/build/args.ts b/src/dev/build/args.ts index 9ee375e33d38f..1124d90be89c6 100644 --- a/src/dev/build/args.ts +++ b/src/dev/build/args.ts @@ -26,6 +26,7 @@ export function readCliArgs(argv: string[]) { 'skip-docker-contexts', 'skip-docker-ubi', 'skip-docker-centos', + 'docker-cloud', 'release', 'skip-node-download', 'verbose', @@ -103,6 +104,7 @@ export function readCliArgs(argv: string[]) { createDebPackage: isOsPackageDesired('deb'), createDockerCentOS: isOsPackageDesired('docker-images') && !Boolean(flags['skip-docker-centos']), + createDockerCloud: isOsPackageDesired('docker-images') && Boolean(flags['docker-cloud']), createDockerUBI: isOsPackageDesired('docker-images') && !Boolean(flags['skip-docker-ubi']), createDockerContexts: !Boolean(flags['skip-docker-contexts']), targetAllPlatforms: Boolean(flags['all-platforms']), diff --git a/src/dev/build/build_distributables.ts b/src/dev/build/build_distributables.ts index 1042cdc484c12..39a62c1fd35dc 100644 --- a/src/dev/build/build_distributables.ts +++ b/src/dev/build/build_distributables.ts @@ -22,6 +22,7 @@ export interface BuildOptions { createDebPackage: boolean; createDockerUBI: boolean; createDockerCentOS: boolean; + createDockerCloud: boolean; createDockerContexts: boolean; versionQualifier: string | undefined; targetAllPlatforms: boolean; @@ -127,6 +128,11 @@ export async function buildDistributables(log: ToolingLog, options: BuildOptions await run(Tasks.CreateDockerCentOS); } + if (options.createDockerCloud) { + // control w/ --docker-images and --docker-cloud + await run(Tasks.CreateDockerCloud); + } + if (options.createDockerContexts) { // control w/ --skip-docker-contexts await run(Tasks.CreateDockerContexts); diff --git a/src/dev/build/tasks/os_packages/create_os_package_tasks.ts b/src/dev/build/tasks/os_packages/create_os_package_tasks.ts index 67a9e86ee2073..ab9a7ce65cbc6 100644 --- a/src/dev/build/tasks/os_packages/create_os_package_tasks.ts +++ b/src/dev/build/tasks/os_packages/create_os_package_tasks.ts @@ -91,6 +91,25 @@ export const CreateDockerUBI: Task = { }, }; +export const CreateDockerCloud: Task = { + description: 'Creating Docker Cloud image', + + async run(config, log, build) { + await runDockerGenerator(config, log, build, { + architecture: 'x64', + context: false, + cloud: true, + image: true, + }); + await runDockerGenerator(config, log, build, { + architecture: 'aarch64', + context: false, + cloud: true, + image: true, + }); + }, +}; + export const CreateDockerContexts: Task = { description: 'Creating Docker build contexts', @@ -111,5 +130,10 @@ export const CreateDockerContexts: Task = { context: true, image: false, }); + await runDockerGenerator(config, log, build, { + cloud: true, + context: true, + image: false, + }); }, }; diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.ts b/src/dev/build/tasks/os_packages/docker_generator/run.ts index cac02cae20c42..c5a4ff64d2188 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/run.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/run.ts @@ -7,7 +7,7 @@ */ import { access, link, unlink, chmod } from 'fs'; -import { resolve } from 'path'; +import { resolve, basename } from 'path'; import { promisify } from 'util'; import { ToolingLog, kibanaPackageJson } from '@kbn/dev-utils'; @@ -32,6 +32,7 @@ export async function runDockerGenerator( image: boolean; ubi?: boolean; ironbank?: boolean; + cloud?: boolean; dockerBuildDate?: string; } ) { @@ -42,6 +43,7 @@ export async function runDockerGenerator( let imageFlavor = ''; if (flags.ubi) imageFlavor += `-${ubiVersionTag}`; if (flags.ironbank) imageFlavor += '-ironbank'; + if (flags.cloud) imageFlavor += '-cloud'; // General docker var config const license = 'Elastic License'; @@ -50,7 +52,10 @@ export async function runDockerGenerator( const artifactArchitecture = flags.architecture === 'aarch64' ? 'aarch64' : 'x86_64'; const artifactPrefix = `kibana-${version}-linux`; const artifactTarball = `${artifactPrefix}-${artifactArchitecture}.tar.gz`; + const metricbeatTarball = `metricbeat-${version}-linux-${artifactArchitecture}.tar.gz`; + const filebeatTarball = `filebeat-${version}-linux-${artifactArchitecture}.tar.gz`; const artifactsDir = config.resolveFromTarget('.'); + const beatsDir = config.resolveFromRepo('.beats'); const dockerBuildDate = flags.dockerBuildDate || new Date().toISOString(); // That would produce oss, default and default-ubi7 const dockerBuildDir = config.resolveFromRepo('build', 'kibana-docker', `default${imageFlavor}`); @@ -58,6 +63,13 @@ export async function runDockerGenerator( const dockerTargetFilename = config.resolveFromTarget( `kibana${imageFlavor}-${version}-docker-image${imageArchitecture}.tar.gz` ); + const dependencies = [ + resolve(artifactsDir, artifactTarball), + ...(flags.cloud + ? [resolve(beatsDir, metricbeatTarball), resolve(beatsDir, filebeatTarball)] + : []), + ]; + const scope: TemplateContext = { artifactPrefix, artifactTarball, @@ -72,6 +84,9 @@ export async function runDockerGenerator( baseOSImage, dockerBuildDate, ubi: flags.ubi, + cloud: flags.cloud, + metricbeatTarball, + filebeatTarball, ironbank: flags.ironbank, architecture: flags.architecture, revision: config.getBuildSha(), @@ -87,26 +102,8 @@ export async function runDockerGenerator( return; } - // Verify if we have the needed kibana target in order - // to build the kibana docker image. - // Also create the docker build target folder - // and delete the current linked target into the - // kibana docker build folder if we have one. - try { - await accessAsync(resolve(artifactsDir, artifactTarball)); - await mkdirp(dockerBuildDir); - await unlinkAsync(resolve(dockerBuildDir, artifactTarball)); - } catch (e) { - if (e && e.code === 'ENOENT' && e.syscall === 'access') { - throw new Error( - `Kibana linux target (${artifactTarball}) is needed in order to build ${''}the docker image. None was found at ${artifactsDir}` - ); - } - } - - // Create the kibana linux target inside the - // Kibana docker build - await linkAsync(resolve(artifactsDir, artifactTarball), resolve(dockerBuildDir, artifactTarball)); + // Create the docker build target folder + await mkdirp(dockerBuildDir); // Write all the needed docker config files // into kibana-docker folder @@ -137,6 +134,21 @@ export async function runDockerGenerator( // Only build images on native targets if (flags.image) { + // Link dependencies + for (const src of dependencies) { + const file = basename(src); + const dest = resolve(dockerBuildDir, file); + try { + await accessAsync(src); + await unlinkAsync(dest); + } catch (e) { + if (e && e.code === 'ENOENT' && e.syscall === 'access') { + throw new Error(`${src} is needed in order to build the docker image.`); + } + } + await linkAsync(src, dest); + } + await exec(log, `./build_docker.sh`, [], { cwd: dockerBuildDir, level: 'info', diff --git a/src/dev/build/tasks/os_packages/docker_generator/template_context.ts b/src/dev/build/tasks/os_packages/docker_generator/template_context.ts index 9c9949c9f57ea..075a3a8808e73 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/template_context.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/template_context.ts @@ -21,6 +21,9 @@ export interface TemplateContext { dockerBuildDate: string; usePublicArtifact?: boolean; ubi?: boolean; + cloud?: boolean; + metricbeatTarball?: string; + filebeatTarball?: string; ironbank?: boolean; revision: string; architecture?: string; diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile index 60dabbffc6312..078741a0d0f6c 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile @@ -24,18 +24,27 @@ RUN cd /opt && \ {{/usePublicArtifact}} {{^usePublicArtifact}} -COPY {{artifactTarball}} /opt/kibana.tar.gz +COPY {{artifactTarball}} /tmp/kibana.tar.gz {{/usePublicArtifact}} RUN mkdir /usr/share/kibana WORKDIR /usr/share/kibana -RUN tar --strip-components=1 -zxf /opt/kibana.tar.gz +RUN tar --strip-components=1 -zxf /tmp/kibana.tar.gz # Ensure that group permissions are the same as user permissions. # This will help when relying on GID-0 to run Kibana, rather than UID-1000. # OpenShift does this, for example. # REF: https://docs.openshift.org/latest/creating_images/guidelines.html RUN chmod -R g=u /usr/share/kibana +{{#cloud}} +COPY {{filebeatTarball}} /tmp/filebeat.tar.gz +COPY {{metricbeatTarball}} /tmp/metricbeat.tar.gz + +RUN mkdir -p /opt/filebeat /opt/metricbeat && \ + tar xf /tmp/filebeat.tar.gz -C /opt/filebeat --strip-components=1 && \ + tar xf /tmp/metricbeat.tar.gz -C /opt/metricbeat --strip-components=1 +{{/cloud}} + ################################################################################ # Build stage 1 (the actual Kibana image): # @@ -86,6 +95,9 @@ RUN fc-cache -v # Bring in Kibana from the initial stage. COPY --from=builder --chown=1000:0 /usr/share/kibana /usr/share/kibana +{{#cloud}} +COPY --from=builder --chown=0:0 /opt /opt +{{/cloud}} WORKDIR /usr/share/kibana RUN ln -s /usr/share/kibana /opt/kibana @@ -146,8 +158,19 @@ RUN mkdir /licenses && \ cp LICENSE.txt /licenses/LICENSE {{/ubi}} -USER kibana - ENTRYPOINT ["/bin/tini", "--"] +{{#cloud}} +CMD ["/app/kibana.sh"] +# Generate a stub command that will be overwritten at runtime +RUN mkdir /app && \ + echo -e '#!/bin/sh\nexec /usr/local/bin/kibana-docker' > /app/kibana.sh && \ + chmod 0555 /app/kibana.sh +{{/cloud}} + +{{^cloud}} CMD ["/usr/local/bin/kibana-docker"] +{{/cloud}} + + +USER kibana From 820b1cafa098220bbc0a7a7cb6779c720422f1a2 Mon Sep 17 00:00:00 2001 From: Madison Caldwell Date: Thu, 9 Sep 2021 22:19:06 -0400 Subject: [PATCH 30/32] 'kibana.alert.rule.from' should be mapped as 'keyword' (#111793) --- .../common/assets/field_maps/technical_rule_field_map.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts index 3c8b96976792d..54a4b80a35bb4 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts @@ -115,7 +115,7 @@ export const technicalRuleFieldMap = { required: false, }, [Fields.ALERT_RULE_FROM]: { - type: 'date', + type: 'keyword', array: false, required: false, }, From 297e4c365f8643e6d3f56698aa34cf148a0eca22 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Thu, 9 Sep 2021 22:13:37 -0700 Subject: [PATCH 31/32] [Reporting/Tests] Use reporting default settings in test server config (#111626) * remove custom kibana server settings for reporting in default x-pack test config * have tests use the deprecated built-in role granting reporting access * restore test user default privilege for canvas * fix app privileges in tests * fix test_user not able to access canvas in the dashboard test * simplify some tests setup * update csv export timerange and snapshot * update fn tests for app privileges * fix feature controls test * Update discover_security.ts * fix reporting tests * test using defaults in the security privilege test * fix read-only privileges with url_create Permalinks * fix security api anonymous * fix anonymous capabilities tests * fix discover csv export tests * Update screenshots.ts * update discover csv fn tests * update snapshots Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apis/security/license_downgrade.ts | 1 - .../apis/security/privileges.ts | 14 +- .../feature_controls/canvas_security.ts | 2 +- x-pack/test/functional/apps/canvas/reports.ts | 9 +- .../reporting/__snapshots__/download_csv.snap | 46 -- .../apps/dashboard/reporting/download_csv.ts | 74 ++- .../apps/dashboard/reporting/screenshots.ts | 9 +- .../discover/__snapshots__/reporting.snap | 491 +++++++++++++++--- .../feature_controls/discover_security.ts | 8 +- .../functional/apps/discover/reporting.ts | 135 ++++- .../functional/apps/lens/lens_reporting.ts | 16 +- .../feature_controls/management_security.ts | 2 +- .../reporting_management/report_listing.ts | 15 +- x-pack/test/functional/config.js | 7 +- .../reporting_and_security.config.ts | 1 + .../reporting_and_security.config.ts | 1 + .../tests/anonymous/capabilities.ts | 36 -- 17 files changed, 637 insertions(+), 230 deletions(-) diff --git a/x-pack/test/api_integration/apis/security/license_downgrade.ts b/x-pack/test/api_integration/apis/security/license_downgrade.ts index dcdcc039bc9d6..a56bb5908ca05 100644 --- a/x-pack/test/api_integration/apis/security/license_downgrade.ts +++ b/x-pack/test/api_integration/apis/security/license_downgrade.ts @@ -26,7 +26,6 @@ export default function ({ getService }: FtrProviderContext) { 'minimal_read', 'url_create', 'store_search_session', - 'generate_report', ]; const trialPrivileges = await supertest .get('/api/security/privileges') diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index bbb0fc60cb3ce..d39d9e599bcc8 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -26,7 +26,7 @@ export default function ({ getService }: FtrProviderContext) { features: { graph: ['all', 'read'], savedObjectsTagging: ['all', 'read'], - canvas: ['all', 'read', 'minimal_all', 'minimal_read', 'generate_report'], + canvas: ['all', 'read'], maps: ['all', 'read'], fleet: ['all', 'read'], actions: ['all', 'read'], @@ -45,16 +45,8 @@ export default function ({ getService }: FtrProviderContext) { 'minimal_read', 'url_create', 'store_search_session', - 'generate_report', - ], - visualize: [ - 'all', - 'read', - 'minimal_all', - 'minimal_read', - 'url_create', - 'generate_report', ], + visualize: ['all', 'read', 'minimal_all', 'minimal_read', 'url_create'], dashboard: [ 'all', 'read', @@ -62,8 +54,6 @@ export default function ({ getService }: FtrProviderContext) { 'minimal_read', 'url_create', 'store_search_session', - 'generate_report', - 'download_csv_report', ], dev_tools: ['all', 'read'], advancedSettings: ['all', 'read'], diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts index 3b5e30e994b71..5a73f31c8427f 100644 --- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts +++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts @@ -33,7 +33,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { kibana: [ { feature: { - canvas: ['minimal_all'], + canvas: ['all'], }, spaces: ['*'], }, diff --git a/x-pack/test/functional/apps/canvas/reports.ts b/x-pack/test/functional/apps/canvas/reports.ts index 32dd89e025855..468430c390030 100644 --- a/x-pack/test/functional/apps/canvas/reports.ts +++ b/x-pack/test/functional/apps/canvas/reports.ts @@ -21,17 +21,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('Canvas PDF Report Generation', () => { before('initialize tests', async () => { log.debug('ReportingPage:initTests'); - await security.role.create('test_reporting_user', { + await security.role.create('test_canvas_user', { elasticsearch: { cluster: [], indices: [], run_as: [] }, kibana: [ { spaces: ['*'], base: [], - feature: { canvas: ['minimal_read', 'generate_report'] }, + feature: { canvas: ['read'] }, }, ], }); - await security.testUser.setRoles(['kibana_admin', 'test_reporting_user']); + await security.testUser.setRoles([ + 'test_canvas_user', + 'reporting_user', // NOTE: the built-in role granting full reporting access is deprecated. See xpack.reporting.roles.enabled + ]); await kibanaServer.importExport.load(archive); await browser.setWindowSize(1600, 850); }); diff --git a/x-pack/test/functional/apps/dashboard/reporting/__snapshots__/download_csv.snap b/x-pack/test/functional/apps/dashboard/reporting/__snapshots__/download_csv.snap index 10384b865c82e..98dc901eaf306 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/__snapshots__/download_csv.snap +++ b/x-pack/test/functional/apps/dashboard/reporting/__snapshots__/download_csv.snap @@ -1,53 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`dashboard Reporting Download CSV E-Commerce Data Download CSV export of a saved search panel 1`] = ` -"\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,45,591503,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0006400064, ZO0150601506\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,12,591709,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0638206382, ZO0038800388\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,52,590937,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0297602976, ZO0565605656\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,29,590976,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0561405614, ZO0281602816\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,41,591598,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0276702767, ZO0291702917\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,590927,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0046600466, ZO0050800508\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,46,591299,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0229002290, ZO0674406744\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,36,591133,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0529905299, ZO0617006170\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,13,591175,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0299402994, ZO0433504335\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,14,591149,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0584905849, ZO0578405784\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,27,591754,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0335803358, ZO0325903259\\" -" -`; - -exports[`dashboard Reporting Download CSV E-Commerce Data Downloads a filtered CSV export of a saved search panel 1`] = ` -"\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,45,591503,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0006400064, ZO0150601506\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,12,591709,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0638206382, ZO0038800388\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,52,590937,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0297602976, ZO0565605656\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,29,590976,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0561405614, ZO0281602816\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,41,591598,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0276702767, ZO0291702917\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,590927,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0046600466, ZO0050800508\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,46,591299,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0229002290, ZO0674406744\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,36,591133,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0529905299, ZO0617006170\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,13,591175,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0299402994, ZO0433504335\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,14,591149,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0584905849, ZO0578405784\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,27,591754,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0335803358, ZO0325903259\\" -" -`; - exports[`dashboard Reporting Download CSV Field Formatters and Scripted Fields Download CSV export of a saved search panel 1`] = ` "date,\\"_id\\",name,gender,value,year,\\"years_ago\\",\\"date_informal\\" -\\"Jan 1, 1984 @ 00:00:00.000\\",\\"1984-Fethany-F\\",Fethany,F,5,1984,\\"35.00000000000000000000\\",\\"Jan 1st 84\\" -\\"Jan 1, 1983 @ 00:00:00.000\\",\\"1983-Fethany-F\\",Fethany,F,\\"1,043\\",1983,\\"36.00000000000000000000\\",\\"Jan 1st 83\\" \\"Jan 1, 1982 @ 00:00:00.000\\",\\"1982-Fethany-F\\",Fethany,F,780,1982,\\"37.00000000000000000000\\",\\"Jan 1st 82\\" -\\"Jan 1, 1981 @ 00:00:00.000\\",\\"1981-Fethany-F\\",Fethany,F,655,1981,\\"38.00000000000000000000\\",\\"Jan 1st 81\\" -\\"Jan 1, 1980 @ 00:00:00.000\\",\\"1980-Fethany-F\\",Fethany,F,702,1980,\\"39.00000000000000000000\\",\\"Jan 1st 80\\" " `; diff --git a/x-pack/test/functional/apps/dashboard/reporting/download_csv.ts b/x-pack/test/functional/apps/dashboard/reporting/download_csv.ts index 94540aa8b4c46..2d6812c61e554 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/download_csv.ts +++ b/x-pack/test/functional/apps/dashboard/reporting/download_csv.ts @@ -83,7 +83,39 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await clickDownloadCsv(); const csvFile = await getDownload(getCsvPath('Ecommerce Data')); - expectSnapshot(csvFile).toMatch(); + const lines = csvFile.trim().split('\n'); + expectSnapshot(csvFile.length).toMatchInline(`782100`); + expectSnapshot(lines.length).toMatchInline(`4676`); + + // instead of matching all 4676 lines of CSV text, this verifies the first 10 and last 10 lines + expectSnapshot(lines.slice(0, 10)).toMatchInline(` + Array [ + "\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,45,591503,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0006400064, ZO0150601506\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,12,591709,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0638206382, ZO0038800388\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,52,590937,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0297602976, ZO0565605656\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,29,590976,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0561405614, ZO0281602816\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,41,591598,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0276702767, ZO0291702917\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,590927,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0046600466, ZO0050800508\\"", + ] + `); + expectSnapshot(lines.slice(-10)).toMatchInline(` + Array [ + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,24,550580,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0144801448, ZO0219602196\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Accessories, Men's Clothing\\",EUR,33,551324,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0316803168, ZO0566905669\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Accessories, Men's Clothing\\",EUR,51,551355,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0313403134, ZO0561205612\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Accessories\\",EUR,28,550957,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0133101331, ZO0189401894\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Accessories, Men's Clothing\\",EUR,39,551154,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0466704667, ZO0617306173\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Accessories\\",EUR,27,551204,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0212602126, ZO0200702007\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,45,550466,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0260702607, ZO0363203632\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,15,550503,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0587505875, ZO0566405664\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Accessories, Women's Shoes\\",EUR,27,550538,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0699406994, ZO0246202462\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,13,550568,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0388403884, ZO0447604476\\"", + ] + `); }); it('Downloads a filtered CSV export of a saved search panel', async function () { @@ -91,13 +123,45 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); // add a filter - await filterBar.addFilter('currency', 'is', 'EUR'); + await filterBar.addFilter('category', 'is', `Men's Shoes`); await clickActionsMenu('EcommerceData'); await clickDownloadCsv(); const csvFile = await getDownload(getCsvPath('Ecommerce Data')); - expectSnapshot(csvFile).toMatch(); + const lines = csvFile.trim().split('\n'); + expectSnapshot(csvFile.length).toMatchInline(`165557`); + expectSnapshot(lines.length).toMatchInline(`945`); + + // instead of matching all 4676 lines of CSV text, this verifies the first 10 and last 10 lines + expectSnapshot(lines.slice(0, 10)).toMatchInline(` + Array [ + "\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,4,591148,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0290302903, ZO0513705137\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,14,591562,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0544305443, ZO0108001080\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,30,591411,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0693506935, ZO0532405324\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,38,722629,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0424204242, ZO0403504035, ZO0506705067, ZO0395603956\\"", + ] + `); + expectSnapshot(lines.slice(-10)).toMatchInline(` + Array [ + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,37,550425,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0256602566, ZO0516305163\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,52,719265,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0619506195, ZO0297802978, ZO0125001250, ZO0693306933\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,34,550990,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0404404044, ZO0570605706\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,7,550663,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0399703997, ZO0560905609\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,34,551697,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0387903879, ZO0693206932\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,9,550784,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0683206832, ZO0687706877\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,15,550412,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0508905089, ZO0681206812\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,23,551556,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0512405124, ZO0551405514\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,550473,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0688006880, ZO0450504505\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,13,550568,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0388403884, ZO0447604476\\"", + ] + `); }); it('Gets the correct filename if panel titles are hidden', async () => { @@ -128,8 +192,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('names dashboard'); await PageObjects.timePicker.setAbsoluteRange( - 'Jan 01, 1980 @ 00:00:00.000', - 'Dec 31, 1984 @ 23:59:59.000' + 'Nov 26, 1981 @ 21:54:15.526', + 'Mar 5, 1982 @ 18:17:44.821' ); await PageObjects.common.sleep(1000); diff --git a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts index 312eba7bd6380..a2523c6d44244 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts +++ b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts @@ -39,7 +39,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await kibanaServer.importExport.load(ecommerceSOPath); await browser.setWindowSize(1600, 850); - await security.role.create('test_reporting_user', { + await security.role.create('test_dashboard_user', { elasticsearch: { cluster: [], indices: [ @@ -55,12 +55,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { { spaces: ['*'], base: [], - feature: { dashboard: ['minimal_all', 'generate_report'] }, + feature: { dashboard: ['minimal_all'] }, }, ], }); - await security.testUser.setRoles(['test_reporting_user']); + await security.testUser.setRoles([ + 'test_dashboard_user', + 'reporting_user', // NOTE: the built-in role granting full reporting access is deprecated. See the xpack.reporting.roles.enabled setting + ]); }); after('clean up archives', async () => { await esArchiver.unload('x-pack/test/functional/es_archives/reporting/ecommerce'); diff --git a/x-pack/test/functional/apps/discover/__snapshots__/reporting.snap b/x-pack/test/functional/apps/discover/__snapshots__/reporting.snap index c7666bf00dd53..09f4698b51bb8 100644 --- a/x-pack/test/functional/apps/discover/__snapshots__/reporting.snap +++ b/x-pack/test/functional/apps/discover/__snapshots__/reporting.snap @@ -1,88 +1,421 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`discover Discover CSV Export Generate CSV: archived search generates a report with data 1`] = ` -"\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,45,591503,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0006400064, ZO0150601506\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,12,591709,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0638206382, ZO0038800388\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,52,590937,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0297602976, ZO0565605656\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,29,590976,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0561405614, ZO0281602816\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,41,591598,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0276702767, ZO0291702917\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,590927,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0046600466, ZO0050800508\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,46,591299,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0229002290, ZO0674406744\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,36,591133,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0529905299, ZO0617006170\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,13,591175,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0299402994, ZO0433504335\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,14,591149,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0584905849, ZO0578405784\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,27,591754,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0335803358, ZO0325903259\\" -" -`; - -exports[`discover Discover CSV Export Generate CSV: archived search generates a report with discover:searchFieldsFromSource = true 1`] = ` -"\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,45,591503,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0006400064, ZO0150601506\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,12,591709,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0638206382, ZO0038800388\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,52,590937,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0297602976, ZO0565605656\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,29,590976,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0561405614, ZO0281602816\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,41,591598,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0276702767, ZO0291702917\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,590927,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0046600466, ZO0050800508\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,46,591299,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0229002290, ZO0674406744\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,36,591133,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0529905299, ZO0617006170\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,13,591175,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0299402994, ZO0433504335\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,14,591149,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0584905849, ZO0578405784\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,27,591754,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0335803358, ZO0325903259\\" -" +exports[`discover Discover CSV Export Generate CSV: new search generates a report from a new search with data: default 1`] = ` +Array [ + "\\"_id\\",\\"_index\\",\\"_score\\",\\"_type\\",category,\\"category.keyword\\",currency,\\"customer_first_name\\",\\"customer_first_name.keyword\\",\\"customer_full_name\\",\\"customer_full_name.keyword\\",\\"customer_gender\\",\\"customer_id\\",\\"customer_last_name\\",\\"customer_last_name.keyword\\",\\"customer_phone\\",\\"day_of_week\\",\\"day_of_week_i\\",email,\\"geoip.city_name\\",\\"geoip.continent_name\\",\\"geoip.country_iso_code\\",\\"geoip.location\\",\\"geoip.region_name\\",manufacturer,\\"manufacturer.keyword\\",\\"order_date\\",\\"order_id\\",\\"products._id\\",\\"products._id.keyword\\",\\"products.base_price\\",\\"products.base_unit_price\\",\\"products.category\\",\\"products.category.keyword\\",\\"products.created_on\\",\\"products.discount_amount\\",\\"products.discount_percentage\\",\\"products.manufacturer\\",\\"products.manufacturer.keyword\\",\\"products.min_price\\",\\"products.price\\",\\"products.product_id\\",\\"products.product_name\\",\\"products.product_name.keyword\\",\\"products.quantity\\",\\"products.sku\\",\\"products.tax_amount\\",\\"products.taxful_price\\",\\"products.taxless_price\\",\\"products.unit_discount_amount\\",sku,\\"taxful_total_price\\",\\"taxless_total_price\\",\\"total_quantity\\",\\"total_unique_products\\",type,user", + "3AMtOW0BH63Xcmy432DJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,\\"Sultan Al\\",\\"Sultan Al\\",\\"Sultan Al Boone\\",\\"Sultan Al Boone\\",MALE,19,Boone,Boone,\\"(empty)\\",Saturday,5,\\"sultan al@boone-family.zzz\\",\\"Abu Dhabi\\",Asia,AE,\\"{", + " \\"\\"coordinates\\"\\": [", + " 54.4,", + " 24.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Abu Dhabi\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Jul 12, 2019 @ 00:00:00.000\\",716724,\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0, 0, 0\\",\\"0, 0, 0, 0\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"42.375, 33, 10.344, 6.109\\",\\"80, 60, 21.984, 11.992\\",\\"23,975, 6,338, 14,116, 15,290\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"1, 1, 1, 1\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",\\"0, 0, 0, 0\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"0, 0, 0, 0\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",174,174,4,4,order,sultan", + "9gMtOW0BH63Xcmy432DJ,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",EUR,Pia,Pia,\\"Pia Richards\\",\\"Pia Richards\\",FEMALE,45,Richards,Richards,\\"(empty)\\",Saturday,5,\\"pia@richards-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Tigress Enterprises, Pyramidustries\\",\\"Tigress Enterprises, Pyramidustries\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591503,\\"sold_product_591503_14761, sold_product_591503_11632\\",\\"sold_product_591503_14761, sold_product_591503_11632\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Tigress Enterprises, Pyramidustries\\",\\"Tigress Enterprises, Pyramidustries\\",\\"10.703, 9.867\\",\\"20.984, 20.984\\",\\"14,761, 11,632\\",\\"Classic heels - blue, Summer dress - coral/pink\\",\\"Classic heels - blue, Summer dress - coral/pink\\",\\"1, 1\\",\\"ZO0006400064, ZO0150601506\\",\\"0, 0\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"0, 0\\",\\"ZO0006400064, ZO0150601506\\",\\"41.969\\",\\"41.969\\",2,2,order,pia", + "BgMtOW0BH63Xcmy432LJ,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing\\",\\"Women's Clothing\\",EUR,Brigitte,Brigitte,\\"Brigitte Meyer\\",\\"Brigitte Meyer\\",FEMALE,12,Meyer,Meyer,\\"(empty)\\",Saturday,5,\\"brigitte@meyer-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Spherecords, Tigress Enterprises\\",\\"Spherecords, Tigress Enterprises\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591709,\\"sold_product_591709_20734, sold_product_591709_7539\\",\\"sold_product_591709_20734, sold_product_591709_7539\\",\\"7.988, 33\\",\\"7.988, 33\\",\\"Women's Clothing, Women's Clothing\\",\\"Women's Clothing, Women's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Spherecords, Tigress Enterprises\\",\\"Spherecords, Tigress Enterprises\\",\\"3.6, 17.484\\",\\"7.988, 33\\",\\"20,734, 7,539\\",\\"Basic T-shirt - dark blue, Summer dress - scarab\\",\\"Basic T-shirt - dark blue, Summer dress - scarab\\",\\"1, 1\\",\\"ZO0638206382, ZO0038800388\\",\\"0, 0\\",\\"7.988, 33\\",\\"7.988, 33\\",\\"0, 0\\",\\"ZO0638206382, ZO0038800388\\",\\"40.969\\",\\"40.969\\",2,2,order,brigitte", + "KQMtOW0BH63Xcmy432LJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Abd,Abd,\\"Abd Mccarthy\\",\\"Abd Mccarthy\\",MALE,52,Mccarthy,Mccarthy,\\"(empty)\\",Saturday,5,\\"abd@mccarthy-family.zzz\\",Cairo,Africa,EG,\\"{", + " \\"\\"coordinates\\"\\": [", + " 31.3,", + " 30.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Cairo Governorate\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590937,\\"sold_product_590937_14438, sold_product_590937_23607\\",\\"sold_product_590937_14438, sold_product_590937_23607\\",\\"28.984, 12.992\\",\\"28.984, 12.992\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"13.344, 6.109\\",\\"28.984, 12.992\\",\\"14,438, 23,607\\",\\"Jumper - dark grey multicolor, Print T-shirt - black\\",\\"Jumper - dark grey multicolor, Print T-shirt - black\\",\\"1, 1\\",\\"ZO0297602976, ZO0565605656\\",\\"0, 0\\",\\"28.984, 12.992\\",\\"28.984, 12.992\\",\\"0, 0\\",\\"ZO0297602976, ZO0565605656\\",\\"41.969\\",\\"41.969\\",2,2,order,abd", + "KgMtOW0BH63Xcmy432LJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Robert,Robert,\\"Robert Banks\\",\\"Robert Banks\\",MALE,29,Banks,Banks,\\"(empty)\\",Saturday,5,\\"robert@banks-family.zzz\\",\\"-\\",Asia,SA,\\"{", + " \\"\\"coordinates\\"\\": [", + " 45,", + " 25", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"-\\",\\"Elitelligence, Oceanavigations\\",\\"Elitelligence, Oceanavigations\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590976,\\"sold_product_590976_21270, sold_product_590976_13220\\",\\"sold_product_590976_21270, sold_product_590976_13220\\",\\"11.992, 24.984\\",\\"11.992, 24.984\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Oceanavigations\\",\\"Elitelligence, Oceanavigations\\",\\"6.23, 12.25\\",\\"11.992, 24.984\\",\\"21,270, 13,220\\",\\"Print T-shirt - white, Chinos - dark grey\\",\\"Print T-shirt - white, Chinos - dark grey\\",\\"1, 1\\",\\"ZO0561405614, ZO0281602816\\",\\"0, 0\\",\\"11.992, 24.984\\",\\"11.992, 24.984\\",\\"0, 0\\",\\"ZO0561405614, ZO0281602816\\",\\"36.969\\",\\"36.969\\",2,2,order,robert", + "awMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Jim,Jim,\\"Jim Hansen\\",\\"Jim Hansen\\",MALE,41,Hansen,Hansen,\\"(empty)\\",Saturday,5,\\"jim@hansen-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Low Tide Media\\",\\"Low Tide Media\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591636,\\"sold_product_591636_1295, sold_product_591636_6498\\",\\"sold_product_591636_1295, sold_product_591636_6498\\",\\"50, 50\\",\\"50, 50\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Low Tide Media\\",\\"Low Tide Media, Low Tide Media\\",\\"25, 27.484\\",\\"50, 50\\",\\"1,295, 6,498\\",\\"Smart lace-ups - dark brown, Suit jacket - dark blue\\",\\"Smart lace-ups - dark brown, Suit jacket - dark blue\\",\\"1, 1\\",\\"ZO0385003850, ZO0408604086\\",\\"0, 0\\",\\"50, 50\\",\\"50, 50\\",\\"0, 0\\",\\"ZO0385003850, ZO0408604086\\",100,100,2,2,order,jim", + "eQMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes\\",\\"Men's Shoes\\",EUR,Thad,Thad,\\"Thad Lamb\\",\\"Thad Lamb\\",MALE,30,Lamb,Lamb,\\"(empty)\\",Saturday,5,\\"thad@lamb-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Elitelligence,Elitelligence,\\"Jul 12, 2019 @ 00:00:00.000\\",591539,\\"sold_product_591539_15260, sold_product_591539_14221\\",\\"sold_product_591539_15260, sold_product_591539_14221\\",\\"20.984, 18.984\\",\\"20.984, 18.984\\",\\"Men's Shoes, Men's Shoes\\",\\"Men's Shoes, Men's Shoes\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Elitelligence\\",\\"Elitelligence, Elitelligence\\",\\"10.078, 10.25\\",\\"20.984, 18.984\\",\\"15,260, 14,221\\",\\"Casual lace-ups - dark blue, Trainers - navy\\",\\"Casual lace-ups - dark blue, Trainers - navy\\",\\"1, 1\\",\\"ZO0505605056, ZO0513605136\\",\\"0, 0\\",\\"20.984, 18.984\\",\\"20.984, 18.984\\",\\"0, 0\\",\\"ZO0505605056, ZO0513605136\\",\\"39.969\\",\\"39.969\\",2,2,order,thad", + "egMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Jim,Jim,\\"Jim Bryant\\",\\"Jim Bryant\\",MALE,41,Bryant,Bryant,\\"(empty)\\",Saturday,5,\\"jim@bryant-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Oceanavigations,Oceanavigations,\\"Jul 12, 2019 @ 00:00:00.000\\",591598,\\"sold_product_591598_20597, sold_product_591598_2774\\",\\"sold_product_591598_20597, sold_product_591598_2774\\",\\"10.992, 85\\",\\"10.992, 85\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Oceanavigations\\",\\"Oceanavigations, Oceanavigations\\",\\"5.93, 45.875\\",\\"10.992, 85\\",\\"20,597, 2,774\\",\\"Tie - brown/black , Classic coat - black\\",\\"Tie - brown/black , Classic coat - black\\",\\"1, 1\\",\\"ZO0276702767, ZO0291702917\\",\\"0, 0\\",\\"10.992, 85\\",\\"10.992, 85\\",\\"0, 0\\",\\"ZO0276702767, ZO0291702917\\",96,96,2,2,order,jim", + "fwMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing\\",\\"Women's Clothing\\",EUR,Betty,Betty,\\"Betty Roberson\\",\\"Betty Roberson\\",FEMALE,44,Roberson,Roberson,\\"(empty)\\",Saturday,5,\\"betty@roberson-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.7", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Tigress Enterprises\\",\\"Tigress Enterprises\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590927,\\"sold_product_590927_15436, sold_product_590927_22598\\",\\"sold_product_590927_15436, sold_product_590927_22598\\",\\"28.984, 28.984\\",\\"28.984, 28.984\\",\\"Women's Clothing, Women's Clothing\\",\\"Women's Clothing, Women's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Tigress Enterprises, Tigress Enterprises\\",\\"Tigress Enterprises, Tigress Enterprises\\",\\"14.781, 14.781\\",\\"28.984, 28.984\\",\\"15,436, 22,598\\",\\"Jersey dress - anthra/black, Shift dress - black\\",\\"Jersey dress - anthra/black, Shift dress - black\\",\\"1, 1\\",\\"ZO0046600466, ZO0050800508\\",\\"0, 0\\",\\"28.984, 28.984\\",\\"28.984, 28.984\\",\\"0, 0\\",\\"ZO0046600466, ZO0050800508\\",\\"57.969\\",\\"57.969\\",2,2,order,betty", + "gAMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing, Men's Shoes\\",\\"Men's Clothing, Men's Shoes\\",EUR,Robbie,Robbie,\\"Robbie Hubbard\\",\\"Robbie Hubbard\\",MALE,48,Hubbard,Hubbard,\\"(empty)\\",Saturday,5,\\"robbie@hubbard-family.zzz\\",Dubai,Asia,AE,\\"{", + " \\"\\"coordinates\\"\\": [", + " 55.3,", + " 25.3", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Dubai,\\"Low Tide Media, Angeldale\\",\\"Low Tide Media, Angeldale\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590970,\\"sold_product_590970_11228, sold_product_590970_12060\\",\\"sold_product_590970_11228, sold_product_590970_12060\\",\\"24.984, 50\\",\\"24.984, 50\\",\\"Men's Clothing, Men's Shoes\\",\\"Men's Clothing, Men's Shoes\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Angeldale\\",\\"Low Tide Media, Angeldale\\",\\"12, 25.984\\",\\"24.984, 50\\",\\"11,228, 12,060\\",\\"Tracksuit top - offwhite multicolor, Lace-ups - black/red\\",\\"Tracksuit top - offwhite multicolor, Lace-ups - black/red\\",\\"1, 1\\",\\"ZO0455604556, ZO0680806808\\",\\"0, 0\\",\\"24.984, 50\\",\\"24.984, 50\\",\\"0, 0\\",\\"ZO0455604556, ZO0680806808\\",75,75,2,2,order,robbie", + "6AMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",EUR,Abigail,Abigail,\\"Abigail Willis\\",\\"Abigail Willis\\",FEMALE,46,Willis,Willis,\\"(empty)\\",Saturday,5,\\"abigail@willis-family.zzz\\",Birmingham,Europe,GB,\\"{", + " \\"\\"coordinates\\"\\": [", + " -1.9,", + " 52.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Birmingham,\\"Tigress Enterprises MAMA, Angeldale\\",\\"Tigress Enterprises MAMA, Angeldale\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591299,\\"sold_product_591299_19895, sold_product_591299_5787\\",\\"sold_product_591299_19895, sold_product_591299_5787\\",\\"33, 85\\",\\"33, 85\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Tigress Enterprises MAMA, Angeldale\\",\\"Tigress Enterprises MAMA, Angeldale\\",\\"17.156, 44.188\\",\\"33, 85\\",\\"19,895, 5,787\\",\\"Summer dress - black/offwhite, Ankle boots - black\\",\\"Summer dress - black/offwhite, Ankle boots - black\\",\\"1, 1\\",\\"ZO0229002290, ZO0674406744\\",\\"0, 0\\",\\"33, 85\\",\\"33, 85\\",\\"0, 0\\",\\"ZO0229002290, ZO0674406744\\",118,118,2,2,order,abigail", + "6QMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Boris,Boris,\\"Boris Greene\\",\\"Boris Greene\\",MALE,36,Greene,Greene,\\"(empty)\\",Saturday,5,\\"boris@greene-family.zzz\\",\\"-\\",Europe,GB,\\"{", + " \\"\\"coordinates\\"\\": [", + " -0.1,", + " 51.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"-\\",\\"Elitelligence, Spritechnologies\\",\\"Elitelligence, Spritechnologies\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591133,\\"sold_product_591133_19496, sold_product_591133_20143\\",\\"sold_product_591133_19496, sold_product_591133_20143\\",\\"24.984, 10.992\\",\\"24.984, 10.992\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Spritechnologies\\",\\"Elitelligence, Spritechnologies\\",\\"12.742, 5.711\\",\\"24.984, 10.992\\",\\"19,496, 20,143\\",\\"Tracksuit bottoms - mottled grey, Sports shirt - black\\",\\"Tracksuit bottoms - mottled grey, Sports shirt - black\\",\\"1, 1\\",\\"ZO0529905299, ZO0617006170\\",\\"0, 0\\",\\"24.984, 10.992\\",\\"24.984, 10.992\\",\\"0, 0\\",\\"ZO0529905299, ZO0617006170\\",\\"35.969\\",\\"35.969\\",2,2,order,boris", + "6gMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Jackson,Jackson,\\"Jackson Conner\\",\\"Jackson Conner\\",MALE,13,Conner,Conner,\\"(empty)\\",Saturday,5,\\"jackson@conner-family.zzz\\",\\"Los Angeles\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -118.2,", + " 34.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",California,\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591175,\\"sold_product_591175_23703, sold_product_591175_11555\\",\\"sold_product_591175_23703, sold_product_591175_11555\\",\\"28.984, 65\\",\\"28.984, 65\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"13.922, 31.844\\",\\"28.984, 65\\",\\"23,703, 11,555\\",\\"Sweatshirt - grey multicolor, Short coat - dark blue\\",\\"Sweatshirt - grey multicolor, Short coat - dark blue\\",\\"1, 1\\",\\"ZO0299402994, ZO0433504335\\",\\"0, 0\\",\\"28.984, 65\\",\\"28.984, 65\\",\\"0, 0\\",\\"ZO0299402994, ZO0433504335\\",94,94,2,2,order,jackson", + "7QMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Yuri,Yuri,\\"Yuri Cross\\",\\"Yuri Cross\\",MALE,21,Cross,Cross,\\"(empty)\\",Saturday,5,\\"yuri@cross-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591297,\\"sold_product_591297_21234, sold_product_591297_17466\\",\\"sold_product_591297_21234, sold_product_591297_17466\\",\\"75, 28.984\\",\\"75, 28.984\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"36.75, 13.344\\",\\"75, 28.984\\",\\"21,234, 17,466\\",\\"Lace-up boots - brown, Jumper - multicoloured\\",\\"Lace-up boots - brown, Jumper - multicoloured\\",\\"1, 1\\",\\"ZO0257502575, ZO0451704517\\",\\"0, 0\\",\\"75, 28.984\\",\\"75, 28.984\\",\\"0, 0\\",\\"ZO0257502575, ZO0451704517\\",104,104,2,2,order,yuri", + "7gMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Irwin,Irwin,\\"Irwin Ramsey\\",\\"Irwin Ramsey\\",MALE,14,Ramsey,Ramsey,\\"(empty)\\",Saturday,5,\\"irwin@ramsey-family.zzz\\",Bogotu00e1,\\"South America\\",CO,\\"{", +] `; -exports[`discover Discover CSV Export Generate CSV: archived search generates a report with filtered data 1`] = ` -"\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,45,591503,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0006400064, ZO0150601506\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,12,591709,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0638206382, ZO0038800388\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,52,590937,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0297602976, ZO0565605656\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,29,590976,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0561405614, ZO0281602816\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,41,591598,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0276702767, ZO0291702917\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,590927,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0046600466, ZO0050800508\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,46,591299,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0229002290, ZO0674406744\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,36,591133,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0529905299, ZO0617006170\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,13,591175,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0299402994, ZO0433504335\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,14,591149,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0584905849, ZO0578405784\\" -\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,27,591754,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0335803358, ZO0325903259\\" -" +exports[`discover Discover CSV Export Generate CSV: new search generates a report from a new search with data: default 2`] = ` +Array [ + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Dubai,\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale\\",\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale\\",\\"Jun 12, 2019 @ 00:00:00.000\\",731056,\\"sold_product_731056_22440, sold_product_731056_13969, sold_product_731056_20215, sold_product_731056_23401\\",\\"sold_product_731056_22440, sold_product_731056_13969, sold_product_731056_20215, sold_product_731056_23401\\",\\"33, 20.984, 75, 13.992\\",\\"33, 20.984, 75, 13.992\\",\\"Women's Clothing, Women's Accessories, Women's Shoes, Women's Accessories\\",\\"Women's Clothing, Women's Accessories, Women's Shoes, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0, 0, 0\\",\\"0, 0, 0, 0\\",\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale, Pyramidustries\\",\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale, Pyramidustries\\",\\"15.18, 10.289, 39, 6.719\\",\\"33, 20.984, 75, 13.992\\",\\"22,440, 13,969, 20,215, 23,401\\",\\"Jersey dress - fan/black, Across body bag - Blue Violety, Boots - black, Hat - nude\\",\\"Jersey dress - fan/black, Across body bag - Blue Violety, Boots - black, Hat - nude\\",\\"1, 1, 1, 1\\",\\"ZO0230102301, ZO0210602106, ZO0679006790, ZO0187301873\\",\\"0, 0, 0, 0\\",\\"33, 20.984, 75, 13.992\\",\\"33, 20.984, 75, 13.992\\",\\"0, 0, 0, 0\\",\\"ZO0230102301, ZO0210602106, ZO0679006790, ZO0187301873\\",143,143,4,4,order,rabbia", + "4AMtOW0BH63Xcmy453H9,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Yahya,Yahya,\\"Yahya Pope\\",\\"Yahya Pope\\",MALE,23,Pope,Pope,\\"(empty)\\",Thursday,3,\\"yahya@pope-family.zzz\\",Marrakesh,Africa,MA,\\"{", + " \\"\\"coordinates\\"\\": [", + " -8,", + " 31.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Marrakech-Tensift-Al Haouz\\",Elitelligence,Elitelligence,\\"Jun 12, 2019 @ 00:00:00.000\\",551556,\\"sold_product_551556_1583, sold_product_551556_11991\\",\\"sold_product_551556_1583, sold_product_551556_11991\\",\\"33, 7.988\\",\\"33, 7.988\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Elitelligence\\",\\"Elitelligence, Elitelligence\\",\\"17.813, 3.76\\",\\"33, 7.988\\",\\"1,583, 11,991\\",\\"High-top trainers - black, Basic T-shirt - black\\",\\"High-top trainers - black, Basic T-shirt - black\\",\\"1, 1\\",\\"ZO0512405124, ZO0551405514\\",\\"0, 0\\",\\"33, 7.988\\",\\"33, 7.988\\",\\"0, 0\\",\\"ZO0512405124, ZO0551405514\\",\\"40.969\\",\\"40.969\\",2,2,order,yahya", + "4QMtOW0BH63Xcmy453H9,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,George,George,\\"George Morrison\\",\\"George Morrison\\",MALE,32,Morrison,Morrison,\\"(empty)\\",Thursday,3,\\"george@morrison-family.zzz\\",Birmingham,Europe,GB,\\"{", + " \\"\\"coordinates\\"\\": [", + " -1.9,", + " 52.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Birmingham,\\"Spritechnologies, Elitelligence\\",\\"Spritechnologies, Elitelligence\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551609,\\"sold_product_551609_3728, sold_product_551609_23435\\",\\"sold_product_551609_3728, sold_product_551609_23435\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Spritechnologies, Elitelligence\\",\\"Spritechnologies, Elitelligence\\",\\"10.703, 10.289\\",\\"20.984, 20.984\\",\\"3,728, 23,435\\",\\"Base layer - khaki, Shirt - red\\",\\"Base layer - khaki, Shirt - red\\",\\"1, 1\\",\\"ZO0630606306, ZO0524705247\\",\\"0, 0\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"0, 0\\",\\"ZO0630606306, ZO0524705247\\",\\"41.969\\",\\"41.969\\",2,2,order,george", + "\\"_wMtOW0BH63Xcmy453H9\\",ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Yuri,Yuri,\\"Yuri Morris\\",\\"Yuri Morris\\",MALE,21,Morris,Morris,\\"(empty)\\",Thursday,3,\\"yuri@morris-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Angeldale, Low Tide Media\\",\\"Angeldale, Low Tide Media\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550473,\\"sold_product_550473_20161, sold_product_550473_6991\\",\\"sold_product_550473_20161, sold_product_550473_6991\\",\\"65, 38\\",\\"65, 38\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Angeldale, Low Tide Media\\",\\"Angeldale, Low Tide Media\\",\\"30.547, 20.125\\",\\"65, 38\\",\\"20,161, 6,991\\",\\"Lace-up boots - dark tan, Jumper - dark blue\\",\\"Lace-up boots - dark tan, Jumper - dark blue\\",\\"1, 1\\",\\"ZO0688006880, ZO0450504505\\",\\"0, 0\\",\\"65, 38\\",\\"65, 38\\",\\"0, 0\\",\\"ZO0688006880, ZO0450504505\\",103,103,2,2,order,yuri", + "AAMtOW0BH63Xcmy453L9,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",EUR,Brigitte,Brigitte,\\"Brigitte Long\\",\\"Brigitte Long\\",FEMALE,12,Long,Long,\\"(empty)\\",Thursday,3,\\"brigitte@long-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Pyramidustries,Pyramidustries,\\"Jun 12, 2019 @ 00:00:00.000\\",550542,\\"sold_product_550542_11839, sold_product_550542_21052\\",\\"sold_product_550542_11839, sold_product_550542_21052\\",\\"24.984, 9.992\\",\\"24.984, 9.992\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries\\",\\"Pyramidustries, Pyramidustries\\",\\"12.992, 4.898\\",\\"24.984, 9.992\\",\\"11,839, 21,052\\",\\"High heeled sandals - cognac, Snood - black/red/green/yellow\\",\\"High heeled sandals - cognac, Snood - black/red/green/yellow\\",\\"1, 1\\",\\"ZO0137301373, ZO0192601926\\",\\"0, 0\\",\\"24.984, 9.992\\",\\"24.984, 9.992\\",\\"0, 0\\",\\"ZO0137301373, ZO0192601926\\",\\"34.969\\",\\"34.969\\",2,2,order,brigitte", + "AQMtOW0BH63Xcmy453L9,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",EUR,rania,rania,\\"rania Barnes\\",\\"rania Barnes\\",FEMALE,24,Barnes,Barnes,\\"(empty)\\",Thursday,3,\\"rania@barnes-family.zzz\\",Cairo,Africa,EG,\\"{", + " \\"\\"coordinates\\"\\": [", + " 31.3,", + " 30.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Cairo Governorate\\",\\"Pyramidustries, Pyramidustries active\\",\\"Pyramidustries, Pyramidustries active\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550580,\\"sold_product_550580_20312, sold_product_550580_10155\\",\\"sold_product_550580_20312, sold_product_550580_10155\\",\\"50, 16.984\\",\\"50, 16.984\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries active\\",\\"Pyramidustries, Pyramidustries active\\",\\"24, 8.656\\",\\"50, 16.984\\",\\"20,312, 10,155\\",\\"Lace-up boots - cognac, Sports shirt - black\\",\\"Lace-up boots - cognac, Sports shirt - black\\",\\"1, 1\\",\\"ZO0144801448, ZO0219602196\\",\\"0, 0\\",\\"50, 16.984\\",\\"50, 16.984\\",\\"0, 0\\",\\"ZO0144801448, ZO0219602196\\",67,67,2,2,order,rani", + "BwMtOW0BH63Xcmy453L9,ecommerce,\\"-\\",\\"-\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",EUR,\\"Abdulraheem Al\\",\\"Abdulraheem Al\\",\\"Abdulraheem Al Tyler\\",\\"Abdulraheem Al Tyler\\",MALE,33,Tyler,Tyler,\\"(empty)\\",Thursday,3,\\"abdulraheem al@tyler-family.zzz\\",\\"Abu Dhabi\\",Asia,AE,\\"{", + " \\"\\"coordinates\\"\\": [", + " 54.4,", + " 24.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Abu Dhabi\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551324,\\"sold_product_551324_14742, sold_product_551324_19089\\",\\"sold_product_551324_14742, sold_product_551324_19089\\",\\"33, 12.992\\",\\"33, 12.992\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"15.18, 7.012\\",\\"33, 12.992\\",\\"14,742, 19,089\\",\\"Laptop bag - brown, Vest - white/dark blue\\",\\"Laptop bag - brown, Vest - white/dark blue\\",\\"1, 1\\",\\"ZO0316803168, ZO0566905669\\",\\"0, 0\\",\\"33, 12.992\\",\\"33, 12.992\\",\\"0, 0\\",\\"ZO0316803168, ZO0566905669\\",\\"45.969\\",\\"45.969\\",2,2,order,abdulraheem", + "mwMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",EUR,Marwan,Marwan,\\"Marwan James\\",\\"Marwan James\\",MALE,51,James,James,\\"(empty)\\",Thursday,3,\\"marwan@james-family.zzz\\",Marrakesh,Africa,MA,\\"{", + " \\"\\"coordinates\\"\\": [", + " -8,", + " 31.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Marrakech-Tensift-Al Haouz\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551355,\\"sold_product_551355_21057, sold_product_551355_23405\\",\\"sold_product_551355_21057, sold_product_551355_23405\\",\\"13.992, 11.992\\",\\"13.992, 11.992\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"6.859, 5.762\\",\\"13.992, 11.992\\",\\"21,057, 23,405\\",\\"Scarf - navy/grey, Basic T-shirt - blue\\",\\"Scarf - navy/grey, Basic T-shirt - blue\\",\\"1, 1\\",\\"ZO0313403134, ZO0561205612\\",\\"0, 0\\",\\"13.992, 11.992\\",\\"13.992, 11.992\\",\\"0, 0\\",\\"ZO0313403134, ZO0561205612\\",\\"25.984\\",\\"25.984\\",2,2,order,marwan", + "twMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",EUR,Sonya,Sonya,\\"Sonya Mccormick\\",\\"Sonya Mccormick\\",FEMALE,28,Mccormick,Mccormick,\\"(empty)\\",Thursday,3,\\"sonya@mccormick-family.zzz\\",Bogotu00e1,\\"South America\\",CO,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74.1,", + " 4.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Bogota D.C.\\",Pyramidustries,Pyramidustries,\\"Jun 12, 2019 @ 00:00:00.000\\",550957,\\"sold_product_550957_22980, sold_product_550957_19828\\",\\"sold_product_550957_22980, sold_product_550957_19828\\",\\"24.984, 16.984\\",\\"24.984, 16.984\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries\\",\\"Pyramidustries, Pyramidustries\\",\\"11.5, 9.172\\",\\"24.984, 16.984\\",\\"22,980, 19,828\\",\\"Classic heels - petrol, Watch - nude\\",\\"Classic heels - petrol, Watch - nude\\",\\"1, 1\\",\\"ZO0133101331, ZO0189401894\\",\\"0, 0\\",\\"24.984, 16.984\\",\\"24.984, 16.984\\",\\"0, 0\\",\\"ZO0133101331, ZO0189401894\\",\\"41.969\\",\\"41.969\\",2,2,order,sonya", + "7AMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",EUR,Kamal,Kamal,\\"Kamal Hansen\\",\\"Kamal Hansen\\",MALE,39,Hansen,Hansen,\\"(empty)\\",Thursday,3,\\"kamal@hansen-family.zzz\\",Istanbul,Asia,TR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 29,", + " 41", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Istanbul,\\"Low Tide Media, Spritechnologies\\",\\"Low Tide Media, Spritechnologies\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551154,\\"sold_product_551154_13181, sold_product_551154_23660\\",\\"sold_product_551154_13181, sold_product_551154_23660\\",\\"42, 11.992\\",\\"42, 11.992\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Spritechnologies\\",\\"Low Tide Media, Spritechnologies\\",\\"21, 6.109\\",\\"42, 11.992\\",\\"13,181, 23,660\\",\\"Briefcase - navy, Sports shirt - Seashell\\",\\"Briefcase - navy, Sports shirt - Seashell\\",\\"1, 1\\",\\"ZO0466704667, ZO0617306173\\",\\"0, 0\\",\\"42, 11.992\\",\\"42, 11.992\\",\\"0, 0\\",\\"ZO0466704667, ZO0617306173\\",\\"53.969\\",\\"53.969\\",2,2,order,kamal", + "7QMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing, Women's Accessories\\",\\"Women's Clothing, Women's Accessories\\",EUR,Elyssa,Elyssa,\\"Elyssa Graves\\",\\"Elyssa Graves\\",FEMALE,27,Graves,Graves,\\"(empty)\\",Thursday,3,\\"elyssa@graves-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Pyramidustries,Pyramidustries,\\"Jun 12, 2019 @ 00:00:00.000\\",551204,\\"sold_product_551204_16805, sold_product_551204_12896\\",\\"sold_product_551204_16805, sold_product_551204_12896\\",\\"13.992, 20.984\\",\\"13.992, 20.984\\",\\"Women's Clothing, Women's Accessories\\",\\"Women's Clothing, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries\\",\\"Pyramidustries, Pyramidustries\\",\\"7.129, 9.656\\",\\"13.992, 20.984\\",\\"16,805, 12,896\\",\\"Bustier - white, Across body bag - cognac\\",\\"Bustier - white, Across body bag - cognac\\",\\"1, 1\\",\\"ZO0212602126, ZO0200702007\\",\\"0, 0\\",\\"13.992, 20.984\\",\\"13.992, 20.984\\",\\"0, 0\\",\\"ZO0212602126, ZO0200702007\\",\\"34.969\\",\\"34.969\\",2,2,order,elyssa", + "7gMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",EUR,Pia,Pia,\\"Pia Rose\\",\\"Pia Rose\\",FEMALE,45,Rose,Rose,\\"(empty)\\",Thursday,3,\\"pia@rose-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Oceanavigations, Primemaster\\",\\"Oceanavigations, Primemaster\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550466,\\"sold_product_550466_19198, sold_product_550466_16409\\",\\"sold_product_550466_19198, sold_product_550466_16409\\",\\"50, 100\\",\\"50, 100\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Primemaster\\",\\"Oceanavigations, Primemaster\\",\\"24, 52\\",\\"50, 100\\",\\"19,198, 16,409\\",\\"Summer dress - grey, Boots - passion\\",\\"Summer dress - grey, Boots - passion\\",\\"1, 1\\",\\"ZO0260702607, ZO0363203632\\",\\"0, 0\\",\\"50, 100\\",\\"50, 100\\",\\"0, 0\\",\\"ZO0260702607, ZO0363203632\\",150,150,2,2,order,pia", + "7wMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Wagdi,Wagdi,\\"Wagdi Boone\\",\\"Wagdi Boone\\",MALE,15,Boone,Boone,\\"(empty)\\",Thursday,3,\\"wagdi@boone-family.zzz\\",\\"-\\",Asia,SA,\\"{", + " \\"\\"coordinates\\"\\": [", + " 45,", + " 25", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"-\\",Elitelligence,Elitelligence,\\"Jun 12, 2019 @ 00:00:00.000\\",550503,\\"sold_product_550503_13211, sold_product_550503_24369\\",\\"sold_product_550503_13211, sold_product_550503_24369\\",\\"34, 11.992\\",\\"34, 11.992\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Elitelligence\\",\\"Elitelligence, Elitelligence\\",\\"15.641, 6.109\\",\\"34, 11.992\\",\\"13,211, 24,369\\",\\"Tracksuit top - black, Print T-shirt - khaki\\",\\"Tracksuit top - black, Print T-shirt - khaki\\",\\"1, 1\\",\\"ZO0587505875, ZO0566405664\\",\\"0, 0\\",\\"34, 11.992\\",\\"34, 11.992\\",\\"0, 0\\",\\"ZO0587505875, ZO0566405664\\",\\"45.969\\",\\"45.969\\",2,2,order,wagdi", + "8AMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Accessories, Women's Shoes\\",\\"Women's Accessories, Women's Shoes\\",EUR,Elyssa,Elyssa,\\"Elyssa Hale\\",\\"Elyssa Hale\\",FEMALE,27,Hale,Hale,\\"(empty)\\",Thursday,3,\\"elyssa@hale-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Angeldale, Oceanavigations\\",\\"Angeldale, Oceanavigations\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550538,\\"sold_product_550538_15047, sold_product_550538_18189\\",\\"sold_product_550538_15047, sold_product_550538_18189\\",\\"75, 60\\",\\"75, 60\\",\\"Women's Accessories, Women's Shoes\\",\\"Women's Accessories, Women's Shoes\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Angeldale, Oceanavigations\\",\\"Angeldale, Oceanavigations\\",\\"34.5, 28.797\\",\\"75, 60\\",\\"15,047, 18,189\\",\\"Handbag - black, Ankle boots - grey\\",\\"Handbag - black, Ankle boots - grey\\",\\"1, 1\\",\\"ZO0699406994, ZO0246202462\\",\\"0, 0\\",\\"75, 60\\",\\"75, 60\\",\\"0, 0\\",\\"ZO0699406994, ZO0246202462\\",135,135,2,2,order,elyssa", + "8QMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Jackson,Jackson,\\"Jackson Love\\",\\"Jackson Love\\",MALE,13,Love,Love,\\"(empty)\\",Thursday,3,\\"jackson@love-family.zzz\\",\\"Los Angeles\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -118.2,", + " 34.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",California,\\"Low Tide Media\\",\\"Low Tide Media\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550568,\\"sold_product_550568_17210, sold_product_550568_12524\\",\\"sold_product_550568_17210, sold_product_550568_12524\\",\\"50, 24.984\\",\\"50, 24.984\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Low Tide Media\\",\\"Low Tide Media, Low Tide Media\\",\\"25, 12.492\\",\\"50, 24.984\\",\\"17,210, 12,524\\",\\"Casual lace-ups - navy, Jumper - dark grey multicolor\\",\\"Casual lace-ups - navy, Jumper - dark grey multicolor\\",\\"1, 1\\",\\"ZO0388403884, ZO0447604476\\",\\"0, 0\\",\\"50, 24.984\\",\\"50, 24.984\\",\\"0, 0\\",\\"ZO0388403884, ZO0447604476\\",75,75,2,2,order,jackson", +] `; -exports[`discover Discover CSV Export Generate CSV: new search generates a report from a new search with data: default 1`] = ` -"\\"_id\\",\\"_index\\",\\"_score\\",\\"_type\\",category,\\"category.keyword\\",currency,\\"customer_first_name\\",\\"customer_first_name.keyword\\",\\"customer_full_name\\",\\"customer_full_name.keyword\\",\\"customer_gender\\",\\"customer_id\\",\\"customer_last_name\\",\\"customer_last_name.keyword\\",\\"customer_phone\\",\\"day_of_week\\",\\"day_of_week_i\\",email,\\"geoip.city_name\\",\\"geoip.continent_name\\",\\"geoip.country_iso_code\\",\\"geoip.location\\",\\"geoip.region_name\\",manufacturer,\\"manufacturer.keyword\\",\\"order_date\\",\\"order_id\\",\\"products._id\\",\\"products._id.keyword\\",\\"products.base_price\\",\\"products.base_unit_price\\",\\"products.category\\",\\"products.category.keyword\\",\\"products.created_on\\",\\"products.discount_amount\\",\\"products.discount_percentage\\",\\"products.manufacturer\\",\\"products.manufacturer.keyword\\",\\"products.min_price\\",\\"products.price\\",\\"products.product_id\\",\\"products.product_name\\",\\"products.product_name.keyword\\",\\"products.quantity\\",\\"products.sku\\",\\"products.tax_amount\\",\\"products.taxful_price\\",\\"products.taxless_price\\",\\"products.unit_discount_amount\\",sku,\\"taxful_total_price\\",\\"taxless_total_price\\",\\"total_quantity\\",\\"total_unique_products\\",type,user -3AMtOW0BH63Xcmy432DJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,\\"Sultan Al\\",\\"Sultan Al\\",\\"Sultan Al Boone\\",\\"Sultan Al Boone\\",MALE,19,Boone,Boone,\\"(empty)\\",Saturday,5,\\"sultan al@boone-family.zzz\\",\\"Abu Dhabi\\",Asia,AE,\\"{ - \\"\\"coordinates\\"\\": [ - 54.4, - 24.5 - ], - \\"\\"type\\"\\": \\"\\"Point\\"\\" -}\\",\\"Abu Dhabi\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Jul 12, 2019 @ 00:00:00.000\\",716724,\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0, 0, 0\\",\\"0, 0, 0, 0\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"42.375, 33, 10.344, 6.109\\",\\"80, 60, 21.984, 11.992\\",\\"23,975, 6,338, 14,116, 15,290\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"1, 1, 1, 1\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",\\"0, 0, 0, 0\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"0, 0, 0, 0\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",174,174,4,4,order,sultan -" +exports[`discover Discover CSV Export Generate CSV: new search generates a report from a new search with data: discover:searchFieldsFromSource 1`] = ` +Array [ + "\\"_id\\",\\"_index\\",\\"_score\\",\\"_type\\",category,\\"category.keyword\\",currency,\\"customer_first_name\\",\\"customer_first_name.keyword\\",\\"customer_full_name\\",\\"customer_full_name.keyword\\",\\"customer_gender\\",\\"customer_id\\",\\"customer_last_name\\",\\"customer_last_name.keyword\\",\\"customer_phone\\",\\"day_of_week\\",\\"day_of_week_i\\",email,\\"geoip.city_name\\",\\"geoip.continent_name\\",\\"geoip.country_iso_code\\",\\"geoip.location\\",\\"geoip.region_name\\",manufacturer,\\"manufacturer.keyword\\",\\"order_date\\",\\"order_id\\",\\"products._id\\",\\"products._id.keyword\\",\\"products.base_price\\",\\"products.base_unit_price\\",\\"products.category\\",\\"products.category.keyword\\",\\"products.created_on\\",\\"products.discount_amount\\",\\"products.discount_percentage\\",\\"products.manufacturer\\",\\"products.manufacturer.keyword\\",\\"products.min_price\\",\\"products.price\\",\\"products.product_id\\",\\"products.product_name\\",\\"products.product_name.keyword\\",\\"products.quantity\\",\\"products.sku\\",\\"products.tax_amount\\",\\"products.taxful_price\\",\\"products.taxless_price\\",\\"products.unit_discount_amount\\",sku,\\"taxful_total_price\\",\\"taxless_total_price\\",\\"total_quantity\\",\\"total_unique_products\\",type,user", + "3AMtOW0BH63Xcmy432DJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,\\"Sultan Al\\",\\"Sultan Al\\",\\"Sultan Al Boone\\",\\"Sultan Al Boone\\",MALE,19,Boone,Boone,\\"(empty)\\",Saturday,5,\\"sultan al@boone-family.zzz\\",\\"Abu Dhabi\\",Asia,AE,\\"{", + " \\"\\"coordinates\\"\\": [", + " 54.4,", + " 24.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Abu Dhabi\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Jul 12, 2019 @ 00:00:00.000\\",716724,\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0, 0, 0\\",\\"0, 0, 0, 0\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"42.375, 33, 10.344, 6.109\\",\\"80, 60, 21.984, 11.992\\",\\"23,975, 6,338, 14,116, 15,290\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"1, 1, 1, 1\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",\\"0, 0, 0, 0\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"0, 0, 0, 0\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",174,174,4,4,order,sultan", + "9gMtOW0BH63Xcmy432DJ,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",EUR,Pia,Pia,\\"Pia Richards\\",\\"Pia Richards\\",FEMALE,45,Richards,Richards,\\"(empty)\\",Saturday,5,\\"pia@richards-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Tigress Enterprises, Pyramidustries\\",\\"Tigress Enterprises, Pyramidustries\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591503,\\"sold_product_591503_14761, sold_product_591503_11632\\",\\"sold_product_591503_14761, sold_product_591503_11632\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Tigress Enterprises, Pyramidustries\\",\\"Tigress Enterprises, Pyramidustries\\",\\"10.703, 9.867\\",\\"20.984, 20.984\\",\\"14,761, 11,632\\",\\"Classic heels - blue, Summer dress - coral/pink\\",\\"Classic heels - blue, Summer dress - coral/pink\\",\\"1, 1\\",\\"ZO0006400064, ZO0150601506\\",\\"0, 0\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"0, 0\\",\\"ZO0006400064, ZO0150601506\\",\\"41.969\\",\\"41.969\\",2,2,order,pia", + "BgMtOW0BH63Xcmy432LJ,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing\\",\\"Women's Clothing\\",EUR,Brigitte,Brigitte,\\"Brigitte Meyer\\",\\"Brigitte Meyer\\",FEMALE,12,Meyer,Meyer,\\"(empty)\\",Saturday,5,\\"brigitte@meyer-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Spherecords, Tigress Enterprises\\",\\"Spherecords, Tigress Enterprises\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591709,\\"sold_product_591709_20734, sold_product_591709_7539\\",\\"sold_product_591709_20734, sold_product_591709_7539\\",\\"7.988, 33\\",\\"7.988, 33\\",\\"Women's Clothing, Women's Clothing\\",\\"Women's Clothing, Women's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Spherecords, Tigress Enterprises\\",\\"Spherecords, Tigress Enterprises\\",\\"3.6, 17.484\\",\\"7.988, 33\\",\\"20,734, 7,539\\",\\"Basic T-shirt - dark blue, Summer dress - scarab\\",\\"Basic T-shirt - dark blue, Summer dress - scarab\\",\\"1, 1\\",\\"ZO0638206382, ZO0038800388\\",\\"0, 0\\",\\"7.988, 33\\",\\"7.988, 33\\",\\"0, 0\\",\\"ZO0638206382, ZO0038800388\\",\\"40.969\\",\\"40.969\\",2,2,order,brigitte", + "KQMtOW0BH63Xcmy432LJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Abd,Abd,\\"Abd Mccarthy\\",\\"Abd Mccarthy\\",MALE,52,Mccarthy,Mccarthy,\\"(empty)\\",Saturday,5,\\"abd@mccarthy-family.zzz\\",Cairo,Africa,EG,\\"{", + " \\"\\"coordinates\\"\\": [", + " 31.3,", + " 30.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Cairo Governorate\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590937,\\"sold_product_590937_14438, sold_product_590937_23607\\",\\"sold_product_590937_14438, sold_product_590937_23607\\",\\"28.984, 12.992\\",\\"28.984, 12.992\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"13.344, 6.109\\",\\"28.984, 12.992\\",\\"14,438, 23,607\\",\\"Jumper - dark grey multicolor, Print T-shirt - black\\",\\"Jumper - dark grey multicolor, Print T-shirt - black\\",\\"1, 1\\",\\"ZO0297602976, ZO0565605656\\",\\"0, 0\\",\\"28.984, 12.992\\",\\"28.984, 12.992\\",\\"0, 0\\",\\"ZO0297602976, ZO0565605656\\",\\"41.969\\",\\"41.969\\",2,2,order,abd", + "KgMtOW0BH63Xcmy432LJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Robert,Robert,\\"Robert Banks\\",\\"Robert Banks\\",MALE,29,Banks,Banks,\\"(empty)\\",Saturday,5,\\"robert@banks-family.zzz\\",\\"-\\",Asia,SA,\\"{", + " \\"\\"coordinates\\"\\": [", + " 45,", + " 25", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"-\\",\\"Elitelligence, Oceanavigations\\",\\"Elitelligence, Oceanavigations\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590976,\\"sold_product_590976_21270, sold_product_590976_13220\\",\\"sold_product_590976_21270, sold_product_590976_13220\\",\\"11.992, 24.984\\",\\"11.992, 24.984\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Oceanavigations\\",\\"Elitelligence, Oceanavigations\\",\\"6.23, 12.25\\",\\"11.992, 24.984\\",\\"21,270, 13,220\\",\\"Print T-shirt - white, Chinos - dark grey\\",\\"Print T-shirt - white, Chinos - dark grey\\",\\"1, 1\\",\\"ZO0561405614, ZO0281602816\\",\\"0, 0\\",\\"11.992, 24.984\\",\\"11.992, 24.984\\",\\"0, 0\\",\\"ZO0561405614, ZO0281602816\\",\\"36.969\\",\\"36.969\\",2,2,order,robert", + "awMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Jim,Jim,\\"Jim Hansen\\",\\"Jim Hansen\\",MALE,41,Hansen,Hansen,\\"(empty)\\",Saturday,5,\\"jim@hansen-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Low Tide Media\\",\\"Low Tide Media\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591636,\\"sold_product_591636_1295, sold_product_591636_6498\\",\\"sold_product_591636_1295, sold_product_591636_6498\\",\\"50, 50\\",\\"50, 50\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Low Tide Media\\",\\"Low Tide Media, Low Tide Media\\",\\"25, 27.484\\",\\"50, 50\\",\\"1,295, 6,498\\",\\"Smart lace-ups - dark brown, Suit jacket - dark blue\\",\\"Smart lace-ups - dark brown, Suit jacket - dark blue\\",\\"1, 1\\",\\"ZO0385003850, ZO0408604086\\",\\"0, 0\\",\\"50, 50\\",\\"50, 50\\",\\"0, 0\\",\\"ZO0385003850, ZO0408604086\\",100,100,2,2,order,jim", + "eQMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes\\",\\"Men's Shoes\\",EUR,Thad,Thad,\\"Thad Lamb\\",\\"Thad Lamb\\",MALE,30,Lamb,Lamb,\\"(empty)\\",Saturday,5,\\"thad@lamb-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Elitelligence,Elitelligence,\\"Jul 12, 2019 @ 00:00:00.000\\",591539,\\"sold_product_591539_15260, sold_product_591539_14221\\",\\"sold_product_591539_15260, sold_product_591539_14221\\",\\"20.984, 18.984\\",\\"20.984, 18.984\\",\\"Men's Shoes, Men's Shoes\\",\\"Men's Shoes, Men's Shoes\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Elitelligence\\",\\"Elitelligence, Elitelligence\\",\\"10.078, 10.25\\",\\"20.984, 18.984\\",\\"15,260, 14,221\\",\\"Casual lace-ups - dark blue, Trainers - navy\\",\\"Casual lace-ups - dark blue, Trainers - navy\\",\\"1, 1\\",\\"ZO0505605056, ZO0513605136\\",\\"0, 0\\",\\"20.984, 18.984\\",\\"20.984, 18.984\\",\\"0, 0\\",\\"ZO0505605056, ZO0513605136\\",\\"39.969\\",\\"39.969\\",2,2,order,thad", + "egMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Jim,Jim,\\"Jim Bryant\\",\\"Jim Bryant\\",MALE,41,Bryant,Bryant,\\"(empty)\\",Saturday,5,\\"jim@bryant-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Oceanavigations,Oceanavigations,\\"Jul 12, 2019 @ 00:00:00.000\\",591598,\\"sold_product_591598_20597, sold_product_591598_2774\\",\\"sold_product_591598_20597, sold_product_591598_2774\\",\\"10.992, 85\\",\\"10.992, 85\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Oceanavigations\\",\\"Oceanavigations, Oceanavigations\\",\\"5.93, 45.875\\",\\"10.992, 85\\",\\"20,597, 2,774\\",\\"Tie - brown/black , Classic coat - black\\",\\"Tie - brown/black , Classic coat - black\\",\\"1, 1\\",\\"ZO0276702767, ZO0291702917\\",\\"0, 0\\",\\"10.992, 85\\",\\"10.992, 85\\",\\"0, 0\\",\\"ZO0276702767, ZO0291702917\\",96,96,2,2,order,jim", + "fwMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing\\",\\"Women's Clothing\\",EUR,Betty,Betty,\\"Betty Roberson\\",\\"Betty Roberson\\",FEMALE,44,Roberson,Roberson,\\"(empty)\\",Saturday,5,\\"betty@roberson-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.7", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Tigress Enterprises\\",\\"Tigress Enterprises\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590927,\\"sold_product_590927_15436, sold_product_590927_22598\\",\\"sold_product_590927_15436, sold_product_590927_22598\\",\\"28.984, 28.984\\",\\"28.984, 28.984\\",\\"Women's Clothing, Women's Clothing\\",\\"Women's Clothing, Women's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Tigress Enterprises, Tigress Enterprises\\",\\"Tigress Enterprises, Tigress Enterprises\\",\\"14.781, 14.781\\",\\"28.984, 28.984\\",\\"15,436, 22,598\\",\\"Jersey dress - anthra/black, Shift dress - black\\",\\"Jersey dress - anthra/black, Shift dress - black\\",\\"1, 1\\",\\"ZO0046600466, ZO0050800508\\",\\"0, 0\\",\\"28.984, 28.984\\",\\"28.984, 28.984\\",\\"0, 0\\",\\"ZO0046600466, ZO0050800508\\",\\"57.969\\",\\"57.969\\",2,2,order,betty", + "gAMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing, Men's Shoes\\",\\"Men's Clothing, Men's Shoes\\",EUR,Robbie,Robbie,\\"Robbie Hubbard\\",\\"Robbie Hubbard\\",MALE,48,Hubbard,Hubbard,\\"(empty)\\",Saturday,5,\\"robbie@hubbard-family.zzz\\",Dubai,Asia,AE,\\"{", + " \\"\\"coordinates\\"\\": [", + " 55.3,", + " 25.3", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Dubai,\\"Low Tide Media, Angeldale\\",\\"Low Tide Media, Angeldale\\",\\"Jul 12, 2019 @ 00:00:00.000\\",590970,\\"sold_product_590970_11228, sold_product_590970_12060\\",\\"sold_product_590970_11228, sold_product_590970_12060\\",\\"24.984, 50\\",\\"24.984, 50\\",\\"Men's Clothing, Men's Shoes\\",\\"Men's Clothing, Men's Shoes\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Angeldale\\",\\"Low Tide Media, Angeldale\\",\\"12, 25.984\\",\\"24.984, 50\\",\\"11,228, 12,060\\",\\"Tracksuit top - offwhite multicolor, Lace-ups - black/red\\",\\"Tracksuit top - offwhite multicolor, Lace-ups - black/red\\",\\"1, 1\\",\\"ZO0455604556, ZO0680806808\\",\\"0, 0\\",\\"24.984, 50\\",\\"24.984, 50\\",\\"0, 0\\",\\"ZO0455604556, ZO0680806808\\",75,75,2,2,order,robbie", + "6AMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",EUR,Abigail,Abigail,\\"Abigail Willis\\",\\"Abigail Willis\\",FEMALE,46,Willis,Willis,\\"(empty)\\",Saturday,5,\\"abigail@willis-family.zzz\\",Birmingham,Europe,GB,\\"{", + " \\"\\"coordinates\\"\\": [", + " -1.9,", + " 52.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Birmingham,\\"Tigress Enterprises MAMA, Angeldale\\",\\"Tigress Enterprises MAMA, Angeldale\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591299,\\"sold_product_591299_19895, sold_product_591299_5787\\",\\"sold_product_591299_19895, sold_product_591299_5787\\",\\"33, 85\\",\\"33, 85\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Tigress Enterprises MAMA, Angeldale\\",\\"Tigress Enterprises MAMA, Angeldale\\",\\"17.156, 44.188\\",\\"33, 85\\",\\"19,895, 5,787\\",\\"Summer dress - black/offwhite, Ankle boots - black\\",\\"Summer dress - black/offwhite, Ankle boots - black\\",\\"1, 1\\",\\"ZO0229002290, ZO0674406744\\",\\"0, 0\\",\\"33, 85\\",\\"33, 85\\",\\"0, 0\\",\\"ZO0229002290, ZO0674406744\\",118,118,2,2,order,abigail", + "6QMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Boris,Boris,\\"Boris Greene\\",\\"Boris Greene\\",MALE,36,Greene,Greene,\\"(empty)\\",Saturday,5,\\"boris@greene-family.zzz\\",\\"-\\",Europe,GB,\\"{", + " \\"\\"coordinates\\"\\": [", + " -0.1,", + " 51.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"-\\",\\"Elitelligence, Spritechnologies\\",\\"Elitelligence, Spritechnologies\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591133,\\"sold_product_591133_19496, sold_product_591133_20143\\",\\"sold_product_591133_19496, sold_product_591133_20143\\",\\"24.984, 10.992\\",\\"24.984, 10.992\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Spritechnologies\\",\\"Elitelligence, Spritechnologies\\",\\"12.742, 5.711\\",\\"24.984, 10.992\\",\\"19,496, 20,143\\",\\"Tracksuit bottoms - mottled grey, Sports shirt - black\\",\\"Tracksuit bottoms - mottled grey, Sports shirt - black\\",\\"1, 1\\",\\"ZO0529905299, ZO0617006170\\",\\"0, 0\\",\\"24.984, 10.992\\",\\"24.984, 10.992\\",\\"0, 0\\",\\"ZO0529905299, ZO0617006170\\",\\"35.969\\",\\"35.969\\",2,2,order,boris", + "6gMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Jackson,Jackson,\\"Jackson Conner\\",\\"Jackson Conner\\",MALE,13,Conner,Conner,\\"(empty)\\",Saturday,5,\\"jackson@conner-family.zzz\\",\\"Los Angeles\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -118.2,", + " 34.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",California,\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591175,\\"sold_product_591175_23703, sold_product_591175_11555\\",\\"sold_product_591175_23703, sold_product_591175_11555\\",\\"28.984, 65\\",\\"28.984, 65\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"13.922, 31.844\\",\\"28.984, 65\\",\\"23,703, 11,555\\",\\"Sweatshirt - grey multicolor, Short coat - dark blue\\",\\"Sweatshirt - grey multicolor, Short coat - dark blue\\",\\"1, 1\\",\\"ZO0299402994, ZO0433504335\\",\\"0, 0\\",\\"28.984, 65\\",\\"28.984, 65\\",\\"0, 0\\",\\"ZO0299402994, ZO0433504335\\",94,94,2,2,order,jackson", + "7QMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Yuri,Yuri,\\"Yuri Cross\\",\\"Yuri Cross\\",MALE,21,Cross,Cross,\\"(empty)\\",Saturday,5,\\"yuri@cross-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"Jul 12, 2019 @ 00:00:00.000\\",591297,\\"sold_product_591297_21234, sold_product_591297_17466\\",\\"sold_product_591297_21234, sold_product_591297_17466\\",\\"75, 28.984\\",\\"75, 28.984\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Low Tide Media\\",\\"Oceanavigations, Low Tide Media\\",\\"36.75, 13.344\\",\\"75, 28.984\\",\\"21,234, 17,466\\",\\"Lace-up boots - brown, Jumper - multicoloured\\",\\"Lace-up boots - brown, Jumper - multicoloured\\",\\"1, 1\\",\\"ZO0257502575, ZO0451704517\\",\\"0, 0\\",\\"75, 28.984\\",\\"75, 28.984\\",\\"0, 0\\",\\"ZO0257502575, ZO0451704517\\",104,104,2,2,order,yuri", + "7gMtOW0BH63Xcmy44WNv,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Irwin,Irwin,\\"Irwin Ramsey\\",\\"Irwin Ramsey\\",MALE,14,Ramsey,Ramsey,\\"(empty)\\",Saturday,5,\\"irwin@ramsey-family.zzz\\",Bogotu00e1,\\"South America\\",CO,\\"{", +] `; -exports[`discover Discover CSV Export Generate CSV: new search generates a report from a new search with data: discover:searchFieldsFromSource 1`] = ` -"\\"_id\\",\\"_index\\",\\"_score\\",\\"_type\\",category,\\"category.keyword\\",currency,\\"customer_first_name\\",\\"customer_first_name.keyword\\",\\"customer_full_name\\",\\"customer_full_name.keyword\\",\\"customer_gender\\",\\"customer_id\\",\\"customer_last_name\\",\\"customer_last_name.keyword\\",\\"customer_phone\\",\\"day_of_week\\",\\"day_of_week_i\\",email,\\"geoip.city_name\\",\\"geoip.continent_name\\",\\"geoip.country_iso_code\\",\\"geoip.location\\",\\"geoip.region_name\\",manufacturer,\\"manufacturer.keyword\\",\\"order_date\\",\\"order_id\\",\\"products._id\\",\\"products._id.keyword\\",\\"products.base_price\\",\\"products.base_unit_price\\",\\"products.category\\",\\"products.category.keyword\\",\\"products.created_on\\",\\"products.discount_amount\\",\\"products.discount_percentage\\",\\"products.manufacturer\\",\\"products.manufacturer.keyword\\",\\"products.min_price\\",\\"products.price\\",\\"products.product_id\\",\\"products.product_name\\",\\"products.product_name.keyword\\",\\"products.quantity\\",\\"products.sku\\",\\"products.tax_amount\\",\\"products.taxful_price\\",\\"products.taxless_price\\",\\"products.unit_discount_amount\\",sku,\\"taxful_total_price\\",\\"taxless_total_price\\",\\"total_quantity\\",\\"total_unique_products\\",type,user -3AMtOW0BH63Xcmy432DJ,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,\\"Sultan Al\\",\\"Sultan Al\\",\\"Sultan Al Boone\\",\\"Sultan Al Boone\\",MALE,19,Boone,Boone,\\"(empty)\\",Saturday,5,\\"sultan al@boone-family.zzz\\",\\"Abu Dhabi\\",Asia,AE,\\"{ - \\"\\"coordinates\\"\\": [ - 54.4, - 24.5 - ], - \\"\\"type\\"\\": \\"\\"Point\\"\\" -}\\",\\"Abu Dhabi\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Angeldale, Oceanavigations, Microlutions\\",\\"Jul 12, 2019 @ 00:00:00.000\\",716724,\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"sold_product_716724_23975, sold_product_716724_6338, sold_product_716724_14116, sold_product_716724_15290\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"0, 0, 0, 0\\",\\"0, 0, 0, 0\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"Angeldale, Oceanavigations, Microlutions, Oceanavigations\\",\\"42.375, 33, 10.344, 6.109\\",\\"80, 60, 21.984, 11.992\\",\\"23,975, 6,338, 14,116, 15,290\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"Winter boots - cognac, Trenchcoat - black, Watch - black, Hat - light grey multicolor\\",\\"1, 1, 1, 1\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",\\"0, 0, 0, 0\\",\\"80, 60, 21.984, 11.992\\",\\"80, 60, 21.984, 11.992\\",\\"0, 0, 0, 0\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\",174,174,4,4,order,sultan -" +exports[`discover Discover CSV Export Generate CSV: new search generates a report from a new search with data: discover:searchFieldsFromSource 2`] = ` +Array [ + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Dubai,\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale\\",\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale\\",\\"Jun 12, 2019 @ 00:00:00.000\\",731056,\\"sold_product_731056_22440, sold_product_731056_13969, sold_product_731056_20215, sold_product_731056_23401\\",\\"sold_product_731056_22440, sold_product_731056_13969, sold_product_731056_20215, sold_product_731056_23401\\",\\"33, 20.984, 75, 13.992\\",\\"33, 20.984, 75, 13.992\\",\\"Women's Clothing, Women's Accessories, Women's Shoes, Women's Accessories\\",\\"Women's Clothing, Women's Accessories, Women's Shoes, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0, 0, 0\\",\\"0, 0, 0, 0\\",\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale, Pyramidustries\\",\\"Tigress Enterprises MAMA, Pyramidustries, Angeldale, Pyramidustries\\",\\"15.18, 10.289, 39, 6.719\\",\\"33, 20.984, 75, 13.992\\",\\"22,440, 13,969, 20,215, 23,401\\",\\"Jersey dress - fan/black, Across body bag - Blue Violety, Boots - black, Hat - nude\\",\\"Jersey dress - fan/black, Across body bag - Blue Violety, Boots - black, Hat - nude\\",\\"1, 1, 1, 1\\",\\"ZO0230102301, ZO0210602106, ZO0679006790, ZO0187301873\\",\\"0, 0, 0, 0\\",\\"33, 20.984, 75, 13.992\\",\\"33, 20.984, 75, 13.992\\",\\"0, 0, 0, 0\\",\\"ZO0230102301, ZO0210602106, ZO0679006790, ZO0187301873\\",143,143,4,4,order,rabbia", + "4AMtOW0BH63Xcmy453H9,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Yahya,Yahya,\\"Yahya Pope\\",\\"Yahya Pope\\",MALE,23,Pope,Pope,\\"(empty)\\",Thursday,3,\\"yahya@pope-family.zzz\\",Marrakesh,Africa,MA,\\"{", + " \\"\\"coordinates\\"\\": [", + " -8,", + " 31.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Marrakech-Tensift-Al Haouz\\",Elitelligence,Elitelligence,\\"Jun 12, 2019 @ 00:00:00.000\\",551556,\\"sold_product_551556_1583, sold_product_551556_11991\\",\\"sold_product_551556_1583, sold_product_551556_11991\\",\\"33, 7.988\\",\\"33, 7.988\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Elitelligence\\",\\"Elitelligence, Elitelligence\\",\\"17.813, 3.76\\",\\"33, 7.988\\",\\"1,583, 11,991\\",\\"High-top trainers - black, Basic T-shirt - black\\",\\"High-top trainers - black, Basic T-shirt - black\\",\\"1, 1\\",\\"ZO0512405124, ZO0551405514\\",\\"0, 0\\",\\"33, 7.988\\",\\"33, 7.988\\",\\"0, 0\\",\\"ZO0512405124, ZO0551405514\\",\\"40.969\\",\\"40.969\\",2,2,order,yahya", + "4QMtOW0BH63Xcmy453H9,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,George,George,\\"George Morrison\\",\\"George Morrison\\",MALE,32,Morrison,Morrison,\\"(empty)\\",Thursday,3,\\"george@morrison-family.zzz\\",Birmingham,Europe,GB,\\"{", + " \\"\\"coordinates\\"\\": [", + " -1.9,", + " 52.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Birmingham,\\"Spritechnologies, Elitelligence\\",\\"Spritechnologies, Elitelligence\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551609,\\"sold_product_551609_3728, sold_product_551609_23435\\",\\"sold_product_551609_3728, sold_product_551609_23435\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Spritechnologies, Elitelligence\\",\\"Spritechnologies, Elitelligence\\",\\"10.703, 10.289\\",\\"20.984, 20.984\\",\\"3,728, 23,435\\",\\"Base layer - khaki, Shirt - red\\",\\"Base layer - khaki, Shirt - red\\",\\"1, 1\\",\\"ZO0630606306, ZO0524705247\\",\\"0, 0\\",\\"20.984, 20.984\\",\\"20.984, 20.984\\",\\"0, 0\\",\\"ZO0630606306, ZO0524705247\\",\\"41.969\\",\\"41.969\\",2,2,order,george", + "\\"_wMtOW0BH63Xcmy453H9\\",ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Yuri,Yuri,\\"Yuri Morris\\",\\"Yuri Morris\\",MALE,21,Morris,Morris,\\"(empty)\\",Thursday,3,\\"yuri@morris-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Angeldale, Low Tide Media\\",\\"Angeldale, Low Tide Media\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550473,\\"sold_product_550473_20161, sold_product_550473_6991\\",\\"sold_product_550473_20161, sold_product_550473_6991\\",\\"65, 38\\",\\"65, 38\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Angeldale, Low Tide Media\\",\\"Angeldale, Low Tide Media\\",\\"30.547, 20.125\\",\\"65, 38\\",\\"20,161, 6,991\\",\\"Lace-up boots - dark tan, Jumper - dark blue\\",\\"Lace-up boots - dark tan, Jumper - dark blue\\",\\"1, 1\\",\\"ZO0688006880, ZO0450504505\\",\\"0, 0\\",\\"65, 38\\",\\"65, 38\\",\\"0, 0\\",\\"ZO0688006880, ZO0450504505\\",103,103,2,2,order,yuri", + "AAMtOW0BH63Xcmy453L9,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",EUR,Brigitte,Brigitte,\\"Brigitte Long\\",\\"Brigitte Long\\",FEMALE,12,Long,Long,\\"(empty)\\",Thursday,3,\\"brigitte@long-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Pyramidustries,Pyramidustries,\\"Jun 12, 2019 @ 00:00:00.000\\",550542,\\"sold_product_550542_11839, sold_product_550542_21052\\",\\"sold_product_550542_11839, sold_product_550542_21052\\",\\"24.984, 9.992\\",\\"24.984, 9.992\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries\\",\\"Pyramidustries, Pyramidustries\\",\\"12.992, 4.898\\",\\"24.984, 9.992\\",\\"11,839, 21,052\\",\\"High heeled sandals - cognac, Snood - black/red/green/yellow\\",\\"High heeled sandals - cognac, Snood - black/red/green/yellow\\",\\"1, 1\\",\\"ZO0137301373, ZO0192601926\\",\\"0, 0\\",\\"24.984, 9.992\\",\\"24.984, 9.992\\",\\"0, 0\\",\\"ZO0137301373, ZO0192601926\\",\\"34.969\\",\\"34.969\\",2,2,order,brigitte", + "AQMtOW0BH63Xcmy453L9,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",EUR,rania,rania,\\"rania Barnes\\",\\"rania Barnes\\",FEMALE,24,Barnes,Barnes,\\"(empty)\\",Thursday,3,\\"rania@barnes-family.zzz\\",Cairo,Africa,EG,\\"{", + " \\"\\"coordinates\\"\\": [", + " 31.3,", + " 30.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Cairo Governorate\\",\\"Pyramidustries, Pyramidustries active\\",\\"Pyramidustries, Pyramidustries active\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550580,\\"sold_product_550580_20312, sold_product_550580_10155\\",\\"sold_product_550580_20312, sold_product_550580_10155\\",\\"50, 16.984\\",\\"50, 16.984\\",\\"Women's Shoes, Women's Clothing\\",\\"Women's Shoes, Women's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries active\\",\\"Pyramidustries, Pyramidustries active\\",\\"24, 8.656\\",\\"50, 16.984\\",\\"20,312, 10,155\\",\\"Lace-up boots - cognac, Sports shirt - black\\",\\"Lace-up boots - cognac, Sports shirt - black\\",\\"1, 1\\",\\"ZO0144801448, ZO0219602196\\",\\"0, 0\\",\\"50, 16.984\\",\\"50, 16.984\\",\\"0, 0\\",\\"ZO0144801448, ZO0219602196\\",67,67,2,2,order,rani", + "BwMtOW0BH63Xcmy453L9,ecommerce,\\"-\\",\\"-\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",EUR,\\"Abdulraheem Al\\",\\"Abdulraheem Al\\",\\"Abdulraheem Al Tyler\\",\\"Abdulraheem Al Tyler\\",MALE,33,Tyler,Tyler,\\"(empty)\\",Thursday,3,\\"abdulraheem al@tyler-family.zzz\\",\\"Abu Dhabi\\",Asia,AE,\\"{", + " \\"\\"coordinates\\"\\": [", + " 54.4,", + " 24.5", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Abu Dhabi\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551324,\\"sold_product_551324_14742, sold_product_551324_19089\\",\\"sold_product_551324_14742, sold_product_551324_19089\\",\\"33, 12.992\\",\\"33, 12.992\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"15.18, 7.012\\",\\"33, 12.992\\",\\"14,742, 19,089\\",\\"Laptop bag - brown, Vest - white/dark blue\\",\\"Laptop bag - brown, Vest - white/dark blue\\",\\"1, 1\\",\\"ZO0316803168, ZO0566905669\\",\\"0, 0\\",\\"33, 12.992\\",\\"33, 12.992\\",\\"0, 0\\",\\"ZO0316803168, ZO0566905669\\",\\"45.969\\",\\"45.969\\",2,2,order,abdulraheem", + "mwMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",EUR,Marwan,Marwan,\\"Marwan James\\",\\"Marwan James\\",MALE,51,James,James,\\"(empty)\\",Thursday,3,\\"marwan@james-family.zzz\\",Marrakesh,Africa,MA,\\"{", + " \\"\\"coordinates\\"\\": [", + " -8,", + " 31.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Marrakech-Tensift-Al Haouz\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551355,\\"sold_product_551355_21057, sold_product_551355_23405\\",\\"sold_product_551355_21057, sold_product_551355_23405\\",\\"13.992, 11.992\\",\\"13.992, 11.992\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Elitelligence\\",\\"Oceanavigations, Elitelligence\\",\\"6.859, 5.762\\",\\"13.992, 11.992\\",\\"21,057, 23,405\\",\\"Scarf - navy/grey, Basic T-shirt - blue\\",\\"Scarf - navy/grey, Basic T-shirt - blue\\",\\"1, 1\\",\\"ZO0313403134, ZO0561205612\\",\\"0, 0\\",\\"13.992, 11.992\\",\\"13.992, 11.992\\",\\"0, 0\\",\\"ZO0313403134, ZO0561205612\\",\\"25.984\\",\\"25.984\\",2,2,order,marwan", + "twMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",EUR,Sonya,Sonya,\\"Sonya Mccormick\\",\\"Sonya Mccormick\\",FEMALE,28,Mccormick,Mccormick,\\"(empty)\\",Thursday,3,\\"sonya@mccormick-family.zzz\\",Bogotu00e1,\\"South America\\",CO,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74.1,", + " 4.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Bogota D.C.\\",Pyramidustries,Pyramidustries,\\"Jun 12, 2019 @ 00:00:00.000\\",550957,\\"sold_product_550957_22980, sold_product_550957_19828\\",\\"sold_product_550957_22980, sold_product_550957_19828\\",\\"24.984, 16.984\\",\\"24.984, 16.984\\",\\"Women's Shoes, Women's Accessories\\",\\"Women's Shoes, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries\\",\\"Pyramidustries, Pyramidustries\\",\\"11.5, 9.172\\",\\"24.984, 16.984\\",\\"22,980, 19,828\\",\\"Classic heels - petrol, Watch - nude\\",\\"Classic heels - petrol, Watch - nude\\",\\"1, 1\\",\\"ZO0133101331, ZO0189401894\\",\\"0, 0\\",\\"24.984, 16.984\\",\\"24.984, 16.984\\",\\"0, 0\\",\\"ZO0133101331, ZO0189401894\\",\\"41.969\\",\\"41.969\\",2,2,order,sonya", + "7AMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",EUR,Kamal,Kamal,\\"Kamal Hansen\\",\\"Kamal Hansen\\",MALE,39,Hansen,Hansen,\\"(empty)\\",Thursday,3,\\"kamal@hansen-family.zzz\\",Istanbul,Asia,TR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 29,", + " 41", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",Istanbul,\\"Low Tide Media, Spritechnologies\\",\\"Low Tide Media, Spritechnologies\\",\\"Jun 12, 2019 @ 00:00:00.000\\",551154,\\"sold_product_551154_13181, sold_product_551154_23660\\",\\"sold_product_551154_13181, sold_product_551154_23660\\",\\"42, 11.992\\",\\"42, 11.992\\",\\"Men's Accessories, Men's Clothing\\",\\"Men's Accessories, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Spritechnologies\\",\\"Low Tide Media, Spritechnologies\\",\\"21, 6.109\\",\\"42, 11.992\\",\\"13,181, 23,660\\",\\"Briefcase - navy, Sports shirt - Seashell\\",\\"Briefcase - navy, Sports shirt - Seashell\\",\\"1, 1\\",\\"ZO0466704667, ZO0617306173\\",\\"0, 0\\",\\"42, 11.992\\",\\"42, 11.992\\",\\"0, 0\\",\\"ZO0466704667, ZO0617306173\\",\\"53.969\\",\\"53.969\\",2,2,order,kamal", + "7QMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing, Women's Accessories\\",\\"Women's Clothing, Women's Accessories\\",EUR,Elyssa,Elyssa,\\"Elyssa Graves\\",\\"Elyssa Graves\\",FEMALE,27,Graves,Graves,\\"(empty)\\",Thursday,3,\\"elyssa@graves-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",Pyramidustries,Pyramidustries,\\"Jun 12, 2019 @ 00:00:00.000\\",551204,\\"sold_product_551204_16805, sold_product_551204_12896\\",\\"sold_product_551204_16805, sold_product_551204_12896\\",\\"13.992, 20.984\\",\\"13.992, 20.984\\",\\"Women's Clothing, Women's Accessories\\",\\"Women's Clothing, Women's Accessories\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Pyramidustries, Pyramidustries\\",\\"Pyramidustries, Pyramidustries\\",\\"7.129, 9.656\\",\\"13.992, 20.984\\",\\"16,805, 12,896\\",\\"Bustier - white, Across body bag - cognac\\",\\"Bustier - white, Across body bag - cognac\\",\\"1, 1\\",\\"ZO0212602126, ZO0200702007\\",\\"0, 0\\",\\"13.992, 20.984\\",\\"13.992, 20.984\\",\\"0, 0\\",\\"ZO0212602126, ZO0200702007\\",\\"34.969\\",\\"34.969\\",2,2,order,elyssa", + "7gMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",EUR,Pia,Pia,\\"Pia Rose\\",\\"Pia Rose\\",FEMALE,45,Rose,Rose,\\"(empty)\\",Thursday,3,\\"pia@rose-family.zzz\\",Cannes,Europe,FR,\\"{", + " \\"\\"coordinates\\"\\": [", + " 7,", + " 43.6", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"Alpes-Maritimes\\",\\"Oceanavigations, Primemaster\\",\\"Oceanavigations, Primemaster\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550466,\\"sold_product_550466_19198, sold_product_550466_16409\\",\\"sold_product_550466_19198, sold_product_550466_16409\\",\\"50, 100\\",\\"50, 100\\",\\"Women's Clothing, Women's Shoes\\",\\"Women's Clothing, Women's Shoes\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Oceanavigations, Primemaster\\",\\"Oceanavigations, Primemaster\\",\\"24, 52\\",\\"50, 100\\",\\"19,198, 16,409\\",\\"Summer dress - grey, Boots - passion\\",\\"Summer dress - grey, Boots - passion\\",\\"1, 1\\",\\"ZO0260702607, ZO0363203632\\",\\"0, 0\\",\\"50, 100\\",\\"50, 100\\",\\"0, 0\\",\\"ZO0260702607, ZO0363203632\\",150,150,2,2,order,pia", + "7wMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Clothing\\",\\"Men's Clothing\\",EUR,Wagdi,Wagdi,\\"Wagdi Boone\\",\\"Wagdi Boone\\",MALE,15,Boone,Boone,\\"(empty)\\",Thursday,3,\\"wagdi@boone-family.zzz\\",\\"-\\",Asia,SA,\\"{", + " \\"\\"coordinates\\"\\": [", + " 45,", + " 25", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"-\\",Elitelligence,Elitelligence,\\"Jun 12, 2019 @ 00:00:00.000\\",550503,\\"sold_product_550503_13211, sold_product_550503_24369\\",\\"sold_product_550503_13211, sold_product_550503_24369\\",\\"34, 11.992\\",\\"34, 11.992\\",\\"Men's Clothing, Men's Clothing\\",\\"Men's Clothing, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Elitelligence, Elitelligence\\",\\"Elitelligence, Elitelligence\\",\\"15.641, 6.109\\",\\"34, 11.992\\",\\"13,211, 24,369\\",\\"Tracksuit top - black, Print T-shirt - khaki\\",\\"Tracksuit top - black, Print T-shirt - khaki\\",\\"1, 1\\",\\"ZO0587505875, ZO0566405664\\",\\"0, 0\\",\\"34, 11.992\\",\\"34, 11.992\\",\\"0, 0\\",\\"ZO0587505875, ZO0566405664\\",\\"45.969\\",\\"45.969\\",2,2,order,wagdi", + "8AMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Women's Accessories, Women's Shoes\\",\\"Women's Accessories, Women's Shoes\\",EUR,Elyssa,Elyssa,\\"Elyssa Hale\\",\\"Elyssa Hale\\",FEMALE,27,Hale,Hale,\\"(empty)\\",Thursday,3,\\"elyssa@hale-family.zzz\\",\\"New York\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -74,", + " 40.8", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",\\"New York\\",\\"Angeldale, Oceanavigations\\",\\"Angeldale, Oceanavigations\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550538,\\"sold_product_550538_15047, sold_product_550538_18189\\",\\"sold_product_550538_15047, sold_product_550538_18189\\",\\"75, 60\\",\\"75, 60\\",\\"Women's Accessories, Women's Shoes\\",\\"Women's Accessories, Women's Shoes\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Angeldale, Oceanavigations\\",\\"Angeldale, Oceanavigations\\",\\"34.5, 28.797\\",\\"75, 60\\",\\"15,047, 18,189\\",\\"Handbag - black, Ankle boots - grey\\",\\"Handbag - black, Ankle boots - grey\\",\\"1, 1\\",\\"ZO0699406994, ZO0246202462\\",\\"0, 0\\",\\"75, 60\\",\\"75, 60\\",\\"0, 0\\",\\"ZO0699406994, ZO0246202462\\",135,135,2,2,order,elyssa", + "8QMtOW0BH63Xcmy46HLV,ecommerce,\\"-\\",\\"-\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",EUR,Jackson,Jackson,\\"Jackson Love\\",\\"Jackson Love\\",MALE,13,Love,Love,\\"(empty)\\",Thursday,3,\\"jackson@love-family.zzz\\",\\"Los Angeles\\",\\"North America\\",US,\\"{", + " \\"\\"coordinates\\"\\": [", + " -118.2,", + " 34.1", + " ],", + " \\"\\"type\\"\\": \\"\\"Point\\"\\"", + "}\\",California,\\"Low Tide Media\\",\\"Low Tide Media\\",\\"Jun 12, 2019 @ 00:00:00.000\\",550568,\\"sold_product_550568_17210, sold_product_550568_12524\\",\\"sold_product_550568_17210, sold_product_550568_12524\\",\\"50, 24.984\\",\\"50, 24.984\\",\\"Men's Shoes, Men's Clothing\\",\\"Men's Shoes, Men's Clothing\\",\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"0, 0\\",\\"0, 0\\",\\"Low Tide Media, Low Tide Media\\",\\"Low Tide Media, Low Tide Media\\",\\"25, 12.492\\",\\"50, 24.984\\",\\"17,210, 12,524\\",\\"Casual lace-ups - navy, Jumper - dark grey multicolor\\",\\"Casual lace-ups - navy, Jumper - dark grey multicolor\\",\\"1, 1\\",\\"ZO0388403884, ZO0447604476\\",\\"0, 0\\",\\"50, 24.984\\",\\"50, 24.984\\",\\"0, 0\\",\\"ZO0388403884, ZO0447604476\\",75,75,2,2,order,jackson", +] `; diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts index 83ad18ed369ae..2010bfd56d2af 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts @@ -229,12 +229,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.share.clickShareTopNavButton(); }); - it(`doesn't show CSV reports`, async () => { - await PageObjects.share.clickShareTopNavButton(); - await testSubjects.missingOrFail('sharePanel-CSVReports'); - await PageObjects.share.clickShareTopNavButton(); - }); - it('allows loading a saved query via the saved query management component', async () => { await savedQueryManagementComponent.loadSavedQuery('OKJpgs'); const queryString = await queryBar.getQueryString(); @@ -322,7 +316,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('Permalinks shows create short-url button', async () => { - await PageObjects.share.clickShareTopNavButton(); + await PageObjects.share.openShareMenuItem('Permalinks'); await PageObjects.share.createShortUrlExistOrFail(); // close the menu await PageObjects.share.clickShareTopNavButton(); diff --git a/x-pack/test/functional/apps/discover/reporting.ts b/x-pack/test/functional/apps/discover/reporting.ts index cb05a59f07917..11a442d3500b5 100644 --- a/x-pack/test/functional/apps/discover/reporting.ts +++ b/x-pack/test/functional/apps/discover/reporting.ts @@ -92,7 +92,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(res.status).to.equal(200); expect(res.get('content-type')).to.equal('text/csv; charset=utf-8'); - expectSnapshot(res.text).toMatch(); + + const csvFile = res.text; + const lines = csvFile.trim().split('\n'); + + // verifies the beginning and end of the text + expectSnapshot(lines.slice(0, 100)).toMatch(); + expectSnapshot(lines.slice(-100)).toMatch(); + + expectSnapshot(csvFile.length).toMatchInline(`5093456`); + expectSnapshot(lines.length).toMatchInline(`32726`); }); it('generates a report from a new search with data: discover:searchFieldsFromSource', async () => { @@ -110,7 +119,17 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(res.status).to.equal(200); expect(res.get('content-type')).to.equal('text/csv; charset=utf-8'); - expectSnapshot(res.text).toMatch(); + + const csvFile = res.text; + const lines = csvFile.trim().split('\n'); + + // verifies the beginning and end of the text + expectSnapshot(lines.slice(0, 100)).toMatch(); + expectSnapshot(lines.slice(-100)).toMatch(); + + expectSnapshot(csvFile.length).toMatchInline(`5093456`); + expectSnapshot(lines.length).toMatchInline(`32726`); + await setFieldsFromSource(false); }); @@ -167,8 +186,40 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await setupPage(); await PageObjects.discover.loadSavedSearch('Ecommerce Data'); - const { text } = await getReport(); - expectSnapshot(text).toMatch(); + const { text: csvFile } = await getReport(); + const lines = csvFile.trim().split('\n'); + expectSnapshot(csvFile.length).toMatchInline(`782100`); + expectSnapshot(lines.length).toMatchInline(`4676`); + + // match the beginning and the end of the csv file contents + expectSnapshot(lines.slice(0, 10)).toMatchInline(` + Array [ + "\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,45,591503,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0006400064, ZO0150601506\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,12,591709,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0638206382, ZO0038800388\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,52,590937,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0297602976, ZO0565605656\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,29,590976,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0561405614, ZO0281602816\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,41,591598,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0276702767, ZO0291702917\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,590927,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0046600466, ZO0050800508\\"", + ] + `); + expectSnapshot(lines.slice(-10)).toMatchInline(` + Array [ + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Clothing\\",EUR,24,550580,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0144801448, ZO0219602196\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Accessories, Men's Clothing\\",EUR,33,551324,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0316803168, ZO0566905669\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Accessories, Men's Clothing\\",EUR,51,551355,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0313403134, ZO0561205612\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Shoes, Women's Accessories\\",EUR,28,550957,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0133101331, ZO0189401894\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Accessories, Men's Clothing\\",EUR,39,551154,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0466704667, ZO0617306173\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Accessories\\",EUR,27,551204,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0212602126, ZO0200702007\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Clothing, Women's Shoes\\",EUR,45,550466,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0260702607, ZO0363203632\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing\\",EUR,15,550503,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0587505875, ZO0566405664\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Women's Accessories, Women's Shoes\\",EUR,27,550538,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0699406994, ZO0246202462\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,13,550568,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0388403884, ZO0447604476\\"", + ] + `); }); it('generates a report with filtered data', async () => { @@ -176,11 +227,44 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.discover.loadSavedSearch('Ecommerce Data'); // filter and re-save - await filterBar.addFilter('currency', 'is', 'EUR'); + await filterBar.addFilter('category', 'is', `Men's Shoes`); await PageObjects.discover.saveSearch(`Ecommerce Data: EUR Filtered`); // renamed the search - const { text } = await getReport(); - expectSnapshot(text).toMatch(); + const { text: csvFile } = await getReport(); + const lines = csvFile.trim().split('\n'); + expectSnapshot(csvFile.length).toMatchInline(`165557`); + expectSnapshot(lines.length).toMatchInline(`945`); + + // match the beginning and the end of the csv file contents + expectSnapshot(lines.slice(0, 10)).toMatchInline(` + Array [ + "\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,4,591148,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0290302903, ZO0513705137\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,14,591562,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0544305443, ZO0108001080\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,30,591411,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0693506935, ZO0532405324\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,38,722629,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0424204242, ZO0403504035, ZO0506705067, ZO0395603956\\"", + ] + `); + expectSnapshot(lines.slice(-10)).toMatchInline(` + Array [ + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,37,550425,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0256602566, ZO0516305163\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,52,719265,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0619506195, ZO0297802978, ZO0125001250, ZO0693306933\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,34,550990,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0404404044, ZO0570605706\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,7,550663,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0399703997, ZO0560905609\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,34,551697,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0387903879, ZO0693206932\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,9,550784,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0683206832, ZO0687706877\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,15,550412,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0508905089, ZO0681206812\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,23,551556,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0512405124, ZO0551405514\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,550473,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0688006880, ZO0450504505\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,13,550568,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0388403884, ZO0447604476\\"", + ] + `); + await PageObjects.discover.saveSearch(`Ecommerce Data`); // rename the search back for the next test }); @@ -191,8 +275,41 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await setFieldsFromSource(true); await browser.refresh(); - const { text } = await getReport(); - expectSnapshot(text).toMatch(); + const { text: csvFile } = await getReport(); + const lines = csvFile.trim().split('\n'); + expectSnapshot(csvFile.length).toMatchInline(`165753`); + expectSnapshot(lines.length).toMatchInline(`945`); + + // match the beginning and the end of the csv file contents + expectSnapshot(lines.slice(0, 10)).toMatchInline(` + Array [ + "\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing, Women's Accessories, Men's Accessories\\",EUR,19,716724,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0687606876, ZO0290502905, ZO0126701267, ZO0308503085\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,41,591636,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0385003850, ZO0408604086\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,30,591539,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0505605056, ZO0513605136\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,48,590970,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0455604556, ZO0680806808\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,591297,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0257502575, ZO0451704517\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,4,591148,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0290302903, ZO0513705137\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,14,591562,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0544305443, ZO0108001080\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,30,591411,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0693506935, ZO0532405324\\"", + "\\"Jul 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,38,722629,5,\\"Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000, Dec 31, 2016 @ 00:00:00.000\\",\\"ZO0424204242, ZO0403504035, ZO0506705067, ZO0395603956\\"", + ] + `); + expectSnapshot(lines.slice(-10)).toMatchInline(` + Array [ + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,37,550425,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0256602566, ZO0516305163\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,52,719265,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0619506195, ZO0297802978, ZO0125001250, ZO0693306933\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,34,550990,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0404404044, ZO0570605706\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,7,550663,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0399703997, ZO0560905609\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,34,551697,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0387903879, ZO0693206932\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,9,550784,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0683206832, ZO0687706877\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes\\",EUR,15,550412,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0508905089, ZO0681206812\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,23,551556,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0512405124, ZO0551405514\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,21,550473,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0688006880, ZO0450504505\\"", + "\\"Jun 12, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,13,550568,3,\\"Dec 1, 2016 @ 00:00:00.000, Dec 1, 2016 @ 00:00:00.000\\",\\"ZO0388403884, ZO0447604476\\"", + ] + `); + await setFieldsFromSource(false); }); }); diff --git a/x-pack/test/functional/apps/lens/lens_reporting.ts b/x-pack/test/functional/apps/lens/lens_reporting.ts index fb4c501baaf80..bd0c003ff3f45 100644 --- a/x-pack/test/functional/apps/lens/lens_reporting.ts +++ b/x-pack/test/functional/apps/lens/lens_reporting.ts @@ -18,18 +18,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('lens reporting', () => { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/lens/reporting'); - await security.role.create('test_reporting_user', { - elasticsearch: { cluster: [], indices: [], run_as: [] }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { dashboard: ['minimal_read', 'generate_report'] }, - }, - ], - }); await security.testUser.setRoles( - ['test_logstash_reader', 'global_dashboard_read', 'test_reporting_user'], + [ + 'test_logstash_reader', + 'global_dashboard_read', + 'reporting_user', // NOTE: the built-in role granting full reporting access is deprecated. See xpack.reporting.roles.enabled + ], false ); }); diff --git a/x-pack/test/functional/apps/management/feature_controls/management_security.ts b/x-pack/test/functional/apps/management/feature_controls/management_security.ts index edca9b64d4fca..b47afc4cda6e4 100644 --- a/x-pack/test/functional/apps/management/feature_controls/management_security.ts +++ b/x-pack/test/functional/apps/management/feature_controls/management_security.ts @@ -64,7 +64,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(sections).to.have.length(2); expect(sections[0]).to.eql({ sectionId: 'insightsAndAlerting', - sectionLinks: ['triggersActions', 'reporting'], + sectionLinks: ['triggersActions'], }); expect(sections[1]).to.eql({ sectionId: 'kibana', diff --git a/x-pack/test/functional/apps/reporting_management/report_listing.ts b/x-pack/test/functional/apps/reporting_management/report_listing.ts index dee09cf678992..1291fb686d8b1 100644 --- a/x-pack/test/functional/apps/reporting_management/report_listing.ts +++ b/x-pack/test/functional/apps/reporting_management/report_listing.ts @@ -20,17 +20,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('Listing of Reports', function () { before(async () => { - await security.role.create('test_reporting_user', { - elasticsearch: { cluster: [], indices: [], run_as: [] }, - kibana: [ - { - spaces: ['*'], - base: [], - feature: { canvas: ['minimal_read', 'generate_report'] }, - }, - ], - }); - await security.testUser.setRoles(['kibana_admin', 'test_reporting_user']); + await security.testUser.setRoles([ + 'kibana_admin', // to access stack management + 'reporting_user', // NOTE: the built-in role granting full reporting access is deprecated. See xpack.reporting.roles.enabled + ]); await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); }); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 0de3df6a04ed8..87a21f815bfd4 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -83,9 +83,6 @@ export default async function ({ readConfigFile }) { '--server.uuid=5b2de169-2785-441b-ae8c-186a1936b17d', '--xpack.maps.showMapsInspectorAdapter=true', '--xpack.maps.preserveDrawingBuffer=true', - '--xpack.reporting.roles.enabled=false', // use the non-deprecated access control model for Reporting - '--xpack.reporting.queue.pollInterval=3000', // make it explicitly the default - '--xpack.reporting.csv.maxSizeBytes=2850', // small-ish limit for cutting off a 1999 byte report '--usageCollection.maximumWaitTimeForAllCollectorsInS=1', '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', @@ -240,8 +237,8 @@ export default async function ({ readConfigFile }) { kibana: [ { feature: { - canvas: ['minimal_all'], - visualize: ['minimal_all'], + canvas: ['all'], + visualize: ['all'], }, spaces: ['*'], }, diff --git a/x-pack/test/reporting_api_integration/reporting_and_security.config.ts b/x-pack/test/reporting_api_integration/reporting_and_security.config.ts index 0d1839c7a138f..b5f75ed7d501c 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security.config.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security.config.ts @@ -36,6 +36,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { `--xpack.reporting.capture.networkPolicy.rules=${JSON.stringify(testPolicyRules)}`, `--xpack.reporting.capture.maxAttempts=1`, `--xpack.reporting.csv.maxSizeBytes=6000`, + '--xpack.reporting.roles.enabled=false', // Reporting access control is implemented by sub-feature application privileges ], }, }; diff --git a/x-pack/test/reporting_functional/reporting_and_security.config.ts b/x-pack/test/reporting_functional/reporting_and_security.config.ts index 536695b4c6dc9..3037aeacde033 100644 --- a/x-pack/test/reporting_functional/reporting_and_security.config.ts +++ b/x-pack/test/reporting_functional/reporting_and_security.config.ts @@ -25,6 +25,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...functionalConfig.get('kbnTestServer.serverArgs'), `--xpack.reporting.capture.maxAttempts=1`, `--xpack.reporting.csv.maxSizeBytes=6000`, + '--xpack.reporting.roles.enabled=false', // Reporting access control is implemented by sub-feature application privileges ], }, services: { diff --git a/x-pack/test/security_api_integration/tests/anonymous/capabilities.ts b/x-pack/test/security_api_integration/tests/anonymous/capabilities.ts index 47d942db947f5..db9715f7e48d5 100644 --- a/x-pack/test/security_api_integration/tests/anonymous/capabilities.ts +++ b/x-pack/test/security_api_integration/tests/anonymous/capabilities.ts @@ -56,8 +56,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -65,7 +63,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -79,7 +76,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": false, @@ -91,8 +87,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -100,7 +94,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -114,7 +107,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": false, @@ -126,8 +118,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -135,7 +125,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -149,7 +138,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": false, @@ -180,8 +168,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -189,7 +175,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -203,7 +188,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": false, @@ -215,8 +199,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -224,7 +206,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -238,7 +219,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": false, @@ -250,8 +230,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -259,7 +237,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -273,7 +250,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": false, @@ -322,8 +298,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": true, "showWriteControls": false, @@ -331,7 +305,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": true, @@ -345,7 +318,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": true, @@ -359,8 +331,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -368,7 +338,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -382,7 +351,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": false, @@ -396,8 +364,6 @@ export default function ({ getService }: FtrProviderContext) { "dashboard": Object { "createNew": false, "createShortUrl": false, - "downloadCsv": false, - "generateScreenshot": false, "saveQuery": false, "show": false, "showWriteControls": false, @@ -405,7 +371,6 @@ export default function ({ getService }: FtrProviderContext) { }, "discover": Object { "createShortUrl": false, - "generateCsv": false, "save": false, "saveQuery": false, "show": false, @@ -419,7 +384,6 @@ export default function ({ getService }: FtrProviderContext) { "visualize": Object { "createShortUrl": false, "delete": false, - "generateScreenshot": false, "save": false, "saveQuery": false, "show": true, From 544d4f6eaa0b32043645673b184efdff4ee7e9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Fri, 10 Sep 2021 09:46:14 +0200 Subject: [PATCH 32/32] [Console] Added information about autocomplete definitions (#105112) * [Console] Added information about autocomplete definitions to the README.md * [Console] Updated README.md * Added code review suggestions Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-spec-to-console/README.md | 5 + src/plugins/console/README.md | 220 ++++++++++++++++++++++++- 2 files changed, 224 insertions(+), 1 deletion(-) diff --git a/packages/kbn-spec-to-console/README.md b/packages/kbn-spec-to-console/README.md index a0e654713f61b..be0ada5e38850 100644 --- a/packages/kbn-spec-to-console/README.md +++ b/packages/kbn-spec-to-console/README.md @@ -29,3 +29,8 @@ yarn spec_to_console -g "/rest-api-spec/src/main/reso * Request bodies * Data fetched at runtime: indices, fields, snapshots, etc * Ad hoc additions + +### Updating the script +When converting query params defined in the REST API specs to console autocompletion definitions, the script relies on a set of known conversion rules specified in [lib/convert/params.js](https://github.com/elastic/kibana/blob/master/packages/kbn-spec-to-console/lib/convert/params.js). +For example, `"keep_on_completion":{"type":"boolean"}` from REST API specs is converted to `"keep_on_completion": "__flag__"` in console autocomplete definitions. +When an unknown parameter type is encountered in REST API specs, the script will throw an `Unexpected type error` and the file [lib/convert/params.js](https://github.com/elastic/kibana/blob/master/packages/kbn-spec-to-console/lib/convert/params.js) needs to be updated by adding a new conversion rule. \ No newline at end of file diff --git a/src/plugins/console/README.md b/src/plugins/console/README.md index e158e82c3702f..3bb58d37d1684 100644 --- a/src/plugins/console/README.md +++ b/src/plugins/console/README.md @@ -8,7 +8,7 @@ Console provides the user with tools for storing and executing requests against ### `load_from` query parameter -The `load_from` query parameter enables opening Console with prepopulated reuqests in two ways: from the elastic.co docs and from within other parts of Kibana. +The `load_from` query parameter enables opening Console with prepopulated requests in two ways: from the elastic.co docs and from within other parts of Kibana. Plugins can open requests in Kibana by assigning this parameter a `data:text/plain` [lz-string](https://pieroxy.net/blog/pages/lz-string/index.html) encoded value. For example, navigating to `/dev_tools#/console?load_from=data:text/plain,OIUQKgBA+gzgpgQwE4GMAWAoA3gIgI4CucSAnjgFy4C2CALulAgDZMVYC+nQA` will prepopulate Console with the following request: @@ -16,3 +16,221 @@ Plugins can open requests in Kibana by assigning this parameter a `data:text/pla GET _search {"query":{"match_all":{}}} ``` + +## Architecture +Console uses Ace editor that is wrapped with [`CoreEditor`](https://github.com/elastic/kibana/blob/master/src/plugins/console/public/types/core_editor.ts), so that if needed it can easily be replaced with another editor, for example Monaco. +The autocomplete logic is located in [`autocomplete`](https://github.com/elastic/kibana/blob/master/src/plugins/console/public/lib/autocomplete) folder. Autocomplete rules are computed by classes in `components` sub-folder. + +## Autocomplete definitions +Kibana users benefit greatly from autocomplete suggestions since not all Elasticsearch APIs can be provided with a corresponding UI. Autocomplete suggestions improve usability of Console for any Elasticsearch API endpoint. +Autocomplete definitions are all created in the form of javascript objects loaded from `json` and `js` files. + +### Creating definitions +The [`generated`](https://github.com/elastic/kibana/blob/master/src/plugins/console/server/lib/spec_definitions/json/generated) folder contains definitions created automatically from Elasticsearch REST API specifications. See this [README](https://github.com/elastic/kibana/blob/master/packages/kbn-spec-to-console/README.md) file for more information on the `spec-to-console` script. + +Manually created override files in the [`overrides`](https://github.com/elastic/kibana/blob/master/src/plugins/console/server/lib/spec_definitions/json/overrides) folder contain fixes for generated files and additions for request body parameters. + +### Top level keys +Use following top level keys in the definitions objects. + +#### `documentation` +Url to Elasticsearch REST API documentation for the endpoint (If the url contains `master` or `current` strings in the path, Console automatically replaces them with the `docLinkVersion` to always redirect the user to the correct version of the documentation). + +#### `methods` +Allowed http methods (`GET`, `POST` etc) + +#### `patterns` +Array of API endpoints that contain variables like `{indices}` or `{fields}`. For example, `{indices}/_rollup/{rollup_index}`. See the [Variables](#variables) section below for more info. + +#### `url_params` +Query url parameters and their values. See the [Query url parameters](#query-url-parameters) section below for more info. An example: +```json +{ + "url_params": { + "format": "", + "local": "__flag__", + "h": [], + "expand_wildcards": [ + "open", + "closed", + "hidden", + "none", + "all" + ] + } +} +``` + +#### `priority` +Value for selecting one autocomplete definition, if several configurations are loaded from the files. The highest number takes precedence. + +#### `data_autocomplete_rules` +Request body parameters and their values. Only used in `overrides` files because REST API specs don't contain any information about body request parameters. +Refer to Elasticsearch REST API documentation when configuring this object. See the [Request body parameters](#request-body-parameters) section below for more info. An example: +```json +{ + "data_autocomplete_rules": { + "text": [], + "field": "{field}", + "analyzer": "", + "explain": { "__one_of": [false, true] } + } +} +``` + +### Query url parameters +Query url parameters are configured in form of an object, for example: +```json +{ + "url_params": { + "local": "__flag__", + "scroll": "", + "expand_wildcards": [ + "open", + "closed", + "hidden", + "none", + "all" + ] + } +} +``` +This object specifies 3 query parameters: `local` (boolean value), `scroll` (no default value) and `expand_wildcards` (with a list of accepted values). + +When the user types in the url path into Console and at least 2 characters after `?`, all matching url parameters are displayed as autocomplete suggestions. In this example, after typing +``` +GET /_some_endpoint?ca +``` +"local" and "expand_wildcards" are displayed as suggestions. +When the user types at least 2 characters after `=`, all matching values for this parameter are displayed as autocomplete suggestions. In this example, after typing +``` +GET /_some_endpoint?expand_wildcards=hi +``` +"hidden" is displayed for autocompletion. + +Variables such as `{indices}` or `{fields}` are accepted both as an url parameter and its value in the configuration object. See the [Variables](#variables) section below for more information. + +### Request body parameters +Request body parameters are configured in form of an object, for example: +```json +{ + "data_autocomplete_rules": { + "index_patterns": [], + "mappings": { "__scope_link": "put_mapping" }, + "version": 0, + "aliases": { + "__template": { + "NAME": {} + } + } + } +} +``` +Object's keys are parameters that will be displayed as autocomplete suggestions when the user starts typing request body. In this example, after typing +``` +PUT /_some_endpoint +{ + " +``` +"index_patterns", "mappings", "version" and "aliases" are displayed as autocomplete suggestions. +Object's values provide default or accepted values of request body parameters. For example, if "version" is selected from the suggestions list, value `0` is automatically filled, resulting in the following request: +``` +PUT /_some_endpoint +{ + "version": 0 +} +``` +Object's values can contain objects for nested configuration because the engine can work recursively while searching for autocomplete suggestions. + +Following values can be used in the configuration object: +#### One value from the list (`__one_of: [..., ...]`) +Use this configuration for a parameter with a list of allowed values, for example types of snapshot repository: +``` +"type": {"__one_of": ["fs", "url", "s3", "hdfs", "azure"]} +``` +The first value in the list will be automatically filled as parameter value. For example, when "type" is selected from the suggestions list, the request body is autofilled as following: +``` +PUT /_some_endpoint +{ + "type": "fs" +} +``` +But if the value `fs` is deleted, all suggestions will be displayed: "fs", "url", "s3", "hdfs" and "azure". +Use `__one_of: [true, false]` for boolean values. + +#### Array of values (`[..., ... ]` or `__any_of: [..., ...]`) +Use this configuration for parameters which accept an array of values, for example actions parameter: +``` +"actions": { "__any_of": [ "add", "remove"]} +``` +When "actions" is selected from the suggestions list, it will be autocompleted with an empty array: +``` +POST /_some_endpoint +{ + "actions": [] +} +``` +All values in the array are displayed as suggestions for parameter values inside the array. + + +#### Default object structure (`__template: {...}`) +Use this configuration to insert an object with default values into the request body when the corresponding key is typed in. +For example, in this configuration +```json +{ + "terms": { + "__template": { + "field": "", + "size": 10 + }, + "field": "{field}", + "size": 10, + "shard_size": 10, + "min_doc_count": 10 + } +} +``` +the `terms` parameter has several properties, but only `field` and `size` are autocompleted in the request body when "terms" is selected from the suggestions list. +``` +POST /_some_endpoint +{ + terms: { + field: '', + size: 10, + } +} +``` +The rest of the properties are displayed as autocomplete suggestions, when the `terms` object is being edited. + +#### Scope link (`__scope_link`) +Use this type to copy a configuration object specified in a different endpoint definition. For example, the `put_settings` endpoint definition contains a configuration object that can be reused for `settings` parameter in a different endpoint: +```json +{ + "data_autocomplete_rules": { + "settings": { + "__scope_link": "put_settings" + } + } +} +``` +#### Global scope (`GLOBAL`) +Use `GLOBAL` keyword with `__scope_link` to refer to a reusable set of definitions created in the [`globals`](https://github.com/elastic/kibana/blob/master/src/plugins/console/server/lib/spec_definitions/js/globals.ts) file. +For example: +```json +{ + "data_autocomplete_rules": { + "query": { + "__scope_link": "GLOBAL.query" + } + } +} +``` +#### Conditional definition (`__condition: { lines_regex: ... }`) +To provide a different set of autocomplete suggestions based on the value configured in the request. For example, when creating a snapshot repository of different types (`fs`, `url` etc) different properties are displayed in the suggestions list based on the type. See [snapshot.create_repository.json](https://github.com/elastic/kibana/blob/master/src/plugins/console/server/lib/spec_definitions/json/overrides/snapshot.create_repository.json) for an example. + + +### Variables +Some autocomplete definitions need to be configured with dynamic values that can't be hard coded into a json or js file, for example a list of indices in the cluster. +A list of variables is defined in the `parametrizedComponentFactories` function in [`kb.js`](https://github.com/elastic/kibana/blob/master/src/plugins/console/public/lib/kb/kb.js) file. The values of these variables are assigned dynamically for every cluster. +Use these variables with curly braces, for example `{indices}`, `{types}`, `{id}`, `{username}`, `{template}`, `{nodes}` etc. +