From 81c5a1f07d515dffeb72558791d70a6e7ad68642 Mon Sep 17 00:00:00 2001 From: Mat Schaffer Date: Wed, 29 Jun 2022 19:15:22 +0900 Subject: [PATCH 01/10] [Logs UI] Wait for loading to finish before typing (#135103) --- .../test/functional/apps/infra/logs_source_configuration.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/infra/logs_source_configuration.ts b/x-pack/test/functional/apps/infra/logs_source_configuration.ts index 5d8afbb9756c7..1a85f6eef2400 100644 --- a/x-pack/test/functional/apps/infra/logs_source_configuration.ts +++ b/x-pack/test/functional/apps/infra/logs_source_configuration.ts @@ -18,7 +18,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const logsUi = getService('logsUi'); const infraSourceConfigurationForm = getService('infraSourceConfigurationForm'); - const pageObjects = getPageObjects(['common', 'infraLogs']); + const pageObjects = getPageObjects(['common', 'header', 'infraLogs']); const retry = getService('retry'); const supertest = getService('supertest'); @@ -45,6 +45,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await infraSourceConfigurationForm.getForm(); }); + await pageObjects.header.waitUntilLoadingHasFinished(); + const nameInput = await infraSourceConfigurationForm.getNameInput(); await nameInput.clearValueWithKeyboard({ charByChar: true }); await nameInput.type('Modified Source'); @@ -71,6 +73,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await infraSourceConfigurationForm.getForm(); }); + await pageObjects.header.waitUntilLoadingHasFinished(); + const logIndicesInput = await infraSourceConfigurationForm.getLogIndicesInput(); await logIndicesInput.clearValueWithKeyboard({ charByChar: true }); await logIndicesInput.type('filebeat-*'); From d266d5de29ee6ccb15745f1bb889c90de75f96e1 Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Wed, 29 Jun 2022 11:20:20 +0100 Subject: [PATCH 02/10] [Security Solution][Detections] fixes Rule selection changes after applying a bulk action (#135291) ## Summary addresses https://github.com/elastic/kibana/issues/125775 Now, after applying bulk action, rules won't be refetched for the following actions: `edit`, `enable`, `disable`. Instead, rules within react-query cache will be updated by bulk edit results. Thus, preventing lost of selection and saves additional http request Issue still can be spotted for `duplicate` action, as all rules need to be refetched to show newly duplicated ones(this should be addressed in https://github.com/elastic/kibana/issues/135297, in the effort to make auto-refresh more friendlier to users) ### Before https://user-images.githubusercontent.com/92328789/176151810-9c1bfee2-32d1-4154-bd52-34e3ca55f1ed.mov ### After https://user-images.githubusercontent.com/92328789/176151475-d45c3484-7a91-477b-b495-d6abeb6f43ab.mov ### Release note - fixes selection change after applying bulk actions (except of duplicating action) --- .../detection_rules/bulk_edit_rules.spec.ts | 28 +++++++++++++++++++ .../cypress/screens/alerts_detection_rules.ts | 2 ++ .../cypress/tasks/alerts_detection_rules.ts | 19 +++++++++---- .../all/bulk_actions/use_bulk_actions.tsx | 20 ++++++++----- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/bulk_edit_rules.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/bulk_edit_rules.spec.ts index dbd73c67e52be..d7dda49df90b6 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/bulk_edit_rules.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/bulk_edit_rules.spec.ts @@ -12,6 +12,8 @@ import { SELECT_ALL_RULES_ON_PAGE_CHECKBOX, LOAD_PREBUILT_RULES_ON_PAGE_HEADER_BTN, RULES_TAGS_FILTER_BTN, + RULE_CHECKBOX, + RULES_TAGS_POPOVER_BTN, RULES_TABLE_REFRESH_INDICATOR, } from '../../screens/alerts_detection_rules'; @@ -30,6 +32,8 @@ import { waitForRulesTableToBeRefreshed, selectNumberOfRules, testAllTagsBadges, + testTagsBadge, + testMultipleSelectedRulesLabel, } from '../../tasks/alerts_detection_rules'; import { @@ -224,4 +228,28 @@ describe('Detection rules, bulk edit', () => { testAllTagsBadges(['overwrite-tag']); }); + + it('should not lose rules selection after edit action', () => { + const rulesCount = 4; + // Switch to 5 rules per page, to have few pages in pagination(ideal way to test auto refresh and selection of few items) + changeRowsPerPageTo(5); + selectNumberOfRules(rulesCount); + + // open add tags form and add 2 new tags + openBulkEditAddTagsForm(); + typeTags(TAGS); + confirmBulkEditForm(); + waitForBulkEditActionToFinish({ rulesCount }); + + testMultipleSelectedRulesLabel(rulesCount); + // check if first four(rulesCount) rules still selected and tags are updated + for (let i = 0; i < rulesCount; i += 1) { + cy.get(RULE_CHECKBOX).eq(i).should('be.checked'); + cy.get(RULES_TAGS_POPOVER_BTN) + .eq(i) + .each(($el) => { + testTagsBadge($el, TAGS); + }); + } + }); }); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts index f72f613d99e8c..3556f46ac8534 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts @@ -124,3 +124,5 @@ export const RULES_TAGS_POPOVER_BTN = '[data-test-subj="tagsDisplayPopoverButton export const RULES_TAGS_POPOVER_WRAPPER = '[data-test-subj="tagsDisplayPopoverWrapper"]'; export const RULES_TAGS_FILTER_BTN = '[data-test-subj="tags-filter-popover-button"]'; + +export const SELECTED_RULES_NUMBER_LABEL = '[data-test-subj="selectedRules"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index eb7eb1836fac4..b5c50d11deb10 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -46,6 +46,7 @@ import { RULE_IMPORT_OVERWRITE_EXCEPTIONS_CHECKBOX, RULES_TAGS_POPOVER_BTN, RULES_TAGS_POPOVER_WRAPPER, + SELECTED_RULES_NUMBER_LABEL, } from '../screens/alerts_detection_rules'; import { ALL_ACTIONS } from '../screens/rule_details'; import { LOADING_INDICATOR } from '../screens/security_header'; @@ -274,12 +275,20 @@ export const importRulesWithOverwriteAll = (rulesFile: string) => { cy.get(INPUT_FILE).should('not.exist'); }; +export const testTagsBadge = ($el: JQuery, tags: string[]) => { + // open tags popover + cy.wrap($el).click(); + cy.get(RULES_TAGS_POPOVER_WRAPPER).should('have.text', tags.join('')); + // close tags popover + cy.wrap($el).click(); +}; + export const testAllTagsBadges = (tags: string[]) => { cy.get(RULES_TAGS_POPOVER_BTN).each(($el) => { - // open tags popover - cy.wrap($el).click(); - cy.get(RULES_TAGS_POPOVER_WRAPPER).should('have.text', tags.join('')); - // close tags popover - cy.wrap($el).click(); + testTagsBadge($el, tags); }); }; + +export const testMultipleSelectedRulesLabel = (rulesCount: number) => { + cy.get(SELECTED_RULES_NUMBER_LABEL).should('have.text', `Selected ${rulesCount} rules`); +}; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx index fc83fc82b9ab7..1c31961690430 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx @@ -38,7 +38,10 @@ import { useAppToasts } from '../../../../../../common/hooks/use_app_toasts'; import { convertRulesFilterToKQL } from '../../../../../containers/detection_engine/rules/utils'; import type { FilterOptions } from '../../../../../containers/detection_engine/rules/types'; -import { useInvalidateRules } from '../../../../../containers/detection_engine/rules/use_find_rules_query'; +import { + useInvalidateRules, + useUpdateRulesCache, +} from '../../../../../containers/detection_engine/rules/use_find_rules_query'; import { BULK_RULE_ACTIONS } from '../../../../../../common/lib/apm/user_actions'; import { useStartTransaction } from '../../../../../../common/lib/apm/use_start_transaction'; @@ -63,6 +66,7 @@ export const useBulkActions = ({ const hasMlPermissions = useHasMlPermissions(); const rulesTableContext = useRulesTableContext(); const invalidateRules = useInvalidateRules(); + const updateRulesCache = useUpdateRulesCache(); const hasActionsPrivileges = useHasActionsPrivileges(); const toasts = useAppToasts(); const getIsMounted = useIsMounted(); @@ -118,14 +122,14 @@ export const useBulkActions = ({ ? disabledRules.map(({ id }) => id) : disabledRulesNoML.map(({ id }) => id); - await executeRulesBulkAction({ + const res = await executeRulesBulkAction({ visibleRuleIds: ruleIds, action: BulkAction.enable, setLoadingRules, toasts, search: isAllSelected ? { query: filterQuery } : { ids: ruleIds }, }); - invalidateRules(); + updateRulesCache(res?.attributes?.results?.updated ?? []); setIsRefreshOn(isRefreshOn); }; @@ -135,14 +139,15 @@ export const useBulkActions = ({ closePopover(); const enabledIds = selectedRules.filter(({ enabled }) => enabled).map(({ id }) => id); - await executeRulesBulkAction({ + + const res = await executeRulesBulkAction({ visibleRuleIds: enabledIds, action: BulkAction.disable, setLoadingRules, toasts, search: isAllSelected ? { query: filterQuery } : { ids: enabledIds }, }); - invalidateRules(); + updateRulesCache(res?.attributes?.results?.updated ?? []); setIsRefreshOn(isRefreshOn); }; @@ -264,7 +269,7 @@ export const useBulkActions = ({ ); }, 5 * 1000); - await executeRulesBulkAction({ + const res = await executeRulesBulkAction({ visibleRuleIds: selectedRuleIds, action: BulkAction.edit, setLoadingRules, @@ -282,7 +287,7 @@ export const useBulkActions = ({ }); isBulkEditFinished = true; - invalidateRules(); + updateRulesCache(res?.attributes?.results?.updated ?? []); setIsRefreshOn(isRefreshOn); if (getIsMounted()) { await resolveTagsRefetch(bulkEditActionType); @@ -455,6 +460,7 @@ export const useBulkActions = ({ filterOptions, getIsMounted, resolveTagsRefetch, + updateRulesCache, isRefreshOn, ] ); From 39af11af42cf1a0a7f35dc3cf76d8f24af624149 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 29 Jun 2022 12:25:59 +0200 Subject: [PATCH 03/10] retry assertions after refresh (#135399) --- .../apps/lens/group1/persistent_context.ts | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/x-pack/test/functional/apps/lens/group1/persistent_context.ts b/x-pack/test/functional/apps/lens/group1/persistent_context.ts index b6c37f8842329..065e1878f1563 100644 --- a/x-pack/test/functional/apps/lens/group1/persistent_context.ts +++ b/x-pack/test/functional/apps/lens/group1/persistent_context.ts @@ -18,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'navigationalSearch', ]); const browser = getService('browser'); + const retry = getService('retry'); const filterBar = getService('filterBar'); const appsMenu = getService('appsMenu'); const security = getService('security'); @@ -186,18 +187,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('keep time range and pinned filters after refresh', async () => { await browser.refresh(); - await PageObjects.header.waitUntilLoadingHasFinished(); - const timeRange = await PageObjects.timePicker.getTimeConfig(); - expect(timeRange.start).to.equal('Sep 7, 2015 @ 06:31:44.000'); - expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000'); - await filterBar.hasFilter('ip', '97.220.3.248', false, true); + // Lens app can take a while to be fully functional after refresh, retry assertion + await retry.try(async () => { + const timeRange = await PageObjects.timePicker.getTimeConfig(); + expect(timeRange.start).to.equal('Sep 7, 2015 @ 06:31:44.000'); + expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000'); + await filterBar.hasFilter('ip', '97.220.3.248', false, true); + }); }); it('keeps selected index pattern after refresh', async () => { await PageObjects.lens.switchDataPanelIndexPattern('log*'); await browser.refresh(); - await PageObjects.header.waitUntilLoadingHasFinished(); - expect(await PageObjects.lens.getDataPanelIndexPattern()).to.equal('log*'); + // Lens app can take a while to be fully functional after refresh, retry assertion + await retry.try(async () => { + expect(await PageObjects.lens.getDataPanelIndexPattern()).to.equal('log*'); + }); }); it('keeps time range and pinned filters after refreshing directly after saving', async () => { @@ -216,11 +221,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); await PageObjects.lens.save('persistentcontext'); await browser.refresh(); - await PageObjects.header.waitUntilLoadingHasFinished(); - const timeRange = await PageObjects.timePicker.getTimeConfig(); - expect(timeRange.start).to.equal('Sep 7, 2015 @ 06:31:44.000'); - expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000'); - await filterBar.hasFilter('ip', '97.220.3.248', false, true); + // Lens app can take a while to be fully functional after refresh, retry assertion + await retry.try(async () => { + const timeRange = await PageObjects.timePicker.getTimeConfig(); + expect(timeRange.start).to.equal('Sep 7, 2015 @ 06:31:44.000'); + expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000'); + await filterBar.hasFilter('ip', '97.220.3.248', false, true); + }); }); }); } From a6f17d5dd28a9aa44eef05f71872e6b6ae8f5a70 Mon Sep 17 00:00:00 2001 From: Tre Date: Wed, 29 Jun 2022 12:56:54 +0100 Subject: [PATCH 04/10] [Archive Migration] x-pack logstash/empty (#135123) * [Archive Migration] x-pack logstash/empty Migrate x-pack logstash/empty Helps with: #102552 This is sorta odd as the archive only has a config and the default space. * Remove the rest. * Already deleting, no need for the clean standard list call. * Already deleting, no need for the delete test. * Drop the created pipeline. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../apis/logstash/pipeline/delete.ts | 44 --- .../apis/logstash/pipeline/index.ts | 1 - .../apis/logstash/pipeline/save.ts | 15 +- .../apps/logstash/pipeline_create.js | 11 +- .../es_archives/logstash/empty/data.json.gz | Bin 246 -> 0 bytes .../es_archives/logstash/empty/mappings.json | 277 ------------------ 6 files changed, 12 insertions(+), 336 deletions(-) delete mode 100644 x-pack/test/api_integration/apis/logstash/pipeline/delete.ts delete mode 100644 x-pack/test/functional/es_archives/logstash/empty/data.json.gz delete mode 100644 x-pack/test/functional/es_archives/logstash/empty/mappings.json diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/delete.ts b/x-pack/test/api_integration/apis/logstash/pipeline/delete.ts deleted file mode 100644 index dc626beb1ba44..0000000000000 --- a/x-pack/test/api_integration/apis/logstash/pipeline/delete.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - describe('delete', () => { - const archive = 'x-pack/test/functional/es_archives/logstash/empty'; - - before('load pipelines archive', async () => { - await esArchiver.load(archive); - - await supertest - .put('/api/logstash/pipeline/fast_generator') - .set('kbn-xsrf', 'xxx') - .send({ - description: 'foobar baz', - pipeline: 'input { generator {} }\n\n output { stdout {} }', - }) - .expect(204); - - await supertest.get('/api/logstash/pipeline/fast_generator').expect(200); - }); - - after('unload pipelines archive', () => { - return esArchiver.unload(archive); - }); - - it('should delete the specified pipeline', async () => { - await supertest - .delete('/api/logstash/pipeline/fast_generator') - .set('kbn-xsrf', 'xxx') - .expect(204); - - await supertest.get('/api/logstash/pipeline/fast_generator').expect(404); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/index.ts b/x-pack/test/api_integration/apis/logstash/pipeline/index.ts index 5e9b82fe8a1a2..c11e3c67aa0c2 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/index.ts +++ b/x-pack/test/api_integration/apis/logstash/pipeline/index.ts @@ -10,6 +10,5 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('pipeline', () => { loadTestFile(require.resolve('./load')); loadTestFile(require.resolve('./save')); - loadTestFile(require.resolve('./delete')); }); } diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/save.ts b/x-pack/test/api_integration/apis/logstash/pipeline/save.ts index 84f6943845b64..01f6e889b35e3 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/save.ts +++ b/x-pack/test/api_integration/apis/logstash/pipeline/save.ts @@ -10,16 +10,15 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - describe('save', () => { - const archive = 'x-pack/test/functional/es_archives/logstash/empty'; - before('load pipelines archive', () => { - return esArchiver.load(archive); - }); + describe('save', () => { + after('delete created pipeline', async () => { + await supertest + .delete('/api/logstash/pipeline/fast_generator') + .set('kbn-xsrf', 'xxx') + .expect(204); - after('unload pipelines archive', () => { - return esArchiver.unload(archive); + await supertest.get('/api/logstash/pipeline/fast_generator').expect(404); }); it('should create the specified pipeline', async () => { diff --git a/x-pack/test/functional/apps/logstash/pipeline_create.js b/x-pack/test/functional/apps/logstash/pipeline_create.js index f576182eb8f21..658b842168468 100644 --- a/x-pack/test/functional/apps/logstash/pipeline_create.js +++ b/x-pack/test/functional/apps/logstash/pipeline_create.js @@ -10,25 +10,26 @@ import { omit } from 'lodash'; export default function ({ getService, getPageObjects }) { const browser = getService('browser'); - const esArchiver = getService('esArchiver'); const random = getService('random'); const pipelineList = getService('pipelineList'); const pipelineEditor = getService('pipelineEditor'); const PageObjects = getPageObjects(['logstash']); const retry = getService('retry'); + const supertest = getService('supertest'); describe('pipeline create new', () => { let originalWindowSize; + let id; before(async () => { + id = random.id(); originalWindowSize = await browser.getWindowSize(); await browser.setWindowSize(1600, 1000); - await esArchiver.load('x-pack/test/functional/es_archives/logstash/empty'); }); - after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/logstash/empty'); + after('delete created pipeline', async () => { await browser.setWindowSize(originalWindowSize.width, originalWindowSize.height); + await supertest.delete(`/api/logstash/pipeline/${id}`).set('kbn-xsrf', 'xxx'); }); it('starts with the default values', async () => { @@ -39,8 +40,6 @@ export default function ({ getService, getPageObjects }) { describe('save button', () => { it('creates the pipeline and redirects to the list', async () => { await PageObjects.logstash.gotoNewPipelineEditor(); - - const id = random.id(); const description = random.text(); const pipeline = random.longText(); const workers = random.int().toString(); diff --git a/x-pack/test/functional/es_archives/logstash/empty/data.json.gz b/x-pack/test/functional/es_archives/logstash/empty/data.json.gz deleted file mode 100644 index 875fdaf6a40bdf939467321f6852d258ccb8cb98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVS`orlLbj^AIa#KcuMr)?tZ(vRxYogj?b1USVw$ld}rSu zff-%WwqQI?+Hr3B&N6*e@L1(LR@LzLw7v(0jm8$D3IESo+JDA;bLi2XG1~_hagkG_ wSC0BXmb3e=BQMek9g1lJQ4DY7qKV;Day(5l{ Date: Wed, 29 Jun 2022 14:11:13 +0200 Subject: [PATCH 05/10] [EBT] Better FTR helper APIs (#135298) --- .../src/plugin_search_paths.ts | 2 +- packages/kbn-pm/dist/index.js | 2 +- src/dev/typescript/projects.ts | 1 + test/analytics/README.md | 6 +- test/analytics/config.ts | 4 +- .../common/fetch_events.ts | 57 ++++++++ .../analytics_ftr_helpers/common/types.ts | 49 +++++++ .../analytics_ftr_helpers/jest.config.js | 19 +++ .../plugins/analytics_ftr_helpers/kibana.json | 0 .../analytics_ftr_helpers/package.json | 2 +- .../public/custom_shipper.ts | 0 .../analytics_ftr_helpers/public/index.ts | 0 .../public/plugin.test.ts | 133 ++++++++++++++++++ .../analytics_ftr_helpers/public/plugin.ts | 26 +--- .../analytics_ftr_helpers/public/types.ts | 7 +- .../server/custom_shipper.ts | 0 .../analytics_ftr_helpers/server/index.ts | 0 .../analytics_ftr_helpers/server/plugin.ts | 45 +++--- .../analytics_ftr_helpers}/tsconfig.json | 1 + .../plugins/analytics_plugin_a/kibana.json | 0 .../plugins/analytics_plugin_a/package.json | 2 +- .../public/custom_shipper.ts | 0 .../analytics_plugin_a/public/index.ts | 0 .../analytics_plugin_a/public/plugin.ts | 0 .../analytics_plugin_a/public/types.ts | 0 .../server/custom_shipper.ts | 0 .../analytics_plugin_a/server/index.ts | 0 .../analytics_plugin_a/server/plugin.ts | 0 .../plugins/analytics_plugin_a}/tsconfig.json | 0 test/analytics/jest.config.js | 13 ++ test/analytics/services/kibana_ebt.ts | 73 +++++----- .../tests/analytics_from_the_browser.ts | 40 +++++- .../tests/analytics_from_the_server.ts | 41 +++++- .../from_the_browser/click.ts | 2 +- .../core_context_providers.ts | 4 +- .../from_the_browser/loaded_kibana.ts | 2 +- .../from_the_server/core_context_providers.ts | 4 +- .../core_overall_status_changed.ts | 6 +- .../from_the_server/kibana_started.ts | 22 +-- test/tsconfig.json | 8 +- tsconfig.base.json | 8 +- 41 files changed, 461 insertions(+), 118 deletions(-) create mode 100644 test/analytics/fixtures/plugins/analytics_ftr_helpers/common/fetch_events.ts create mode 100644 test/analytics/fixtures/plugins/analytics_ftr_helpers/common/types.ts create mode 100644 test/analytics/fixtures/plugins/analytics_ftr_helpers/jest.config.js rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/kibana.json (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/package.json (80%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/public/custom_shipper.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/public/index.ts (100%) create mode 100644 test/analytics/fixtures/plugins/analytics_ftr_helpers/public/plugin.test.ts rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/public/plugin.ts (52%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/public/types.ts (63%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/server/custom_shipper.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/server/index.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_ftr_helpers/server/plugin.ts (64%) rename test/analytics/{__fixtures__/plugins/analytics_plugin_a => fixtures/plugins/analytics_ftr_helpers}/tsconfig.json (93%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/kibana.json (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/package.json (81%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/public/custom_shipper.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/public/index.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/public/plugin.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/public/types.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/server/custom_shipper.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/server/index.ts (100%) rename test/analytics/{__fixtures__ => fixtures}/plugins/analytics_plugin_a/server/plugin.ts (100%) rename test/analytics/{__fixtures__/plugins/analytics_ftr_helpers => fixtures/plugins/analytics_plugin_a}/tsconfig.json (100%) create mode 100644 test/analytics/jest.config.js diff --git a/packages/kbn-plugin-discovery/src/plugin_search_paths.ts b/packages/kbn-plugin-discovery/src/plugin_search_paths.ts index 5d46c0c8de868..dce55698e88ee 100644 --- a/packages/kbn-plugin-discovery/src/plugin_search_paths.ts +++ b/packages/kbn-plugin-discovery/src/plugin_search_paths.ts @@ -25,7 +25,7 @@ export function getPluginSearchPaths({ rootDir, oss, examples, testPlugins }: Se resolve(rootDir, '..', 'kibana-extra'), ...(testPlugins ? [ - resolve(rootDir, 'test/analytics/__fixtures__/plugins'), + resolve(rootDir, 'test/analytics/fixtures/plugins'), resolve(rootDir, 'test/plugin_functional/plugins'), resolve(rootDir, 'test/interpreter_functional/plugins'), resolve(rootDir, 'test/common/fixtures/plugins'), diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 3df97ff607ad8..3c68dc90dda18 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -2168,7 +2168,7 @@ function getPluginSearchPaths({ examples, testPlugins }) { - return [(0, _path.resolve)(rootDir, 'src', 'plugins'), ...(oss ? [] : [(0, _path.resolve)(rootDir, 'x-pack', 'plugins')]), (0, _path.resolve)(rootDir, 'plugins'), ...(examples ? [(0, _path.resolve)(rootDir, 'examples')] : []), ...(examples && !oss ? [(0, _path.resolve)(rootDir, 'x-pack', 'examples')] : []), (0, _path.resolve)(rootDir, '..', 'kibana-extra'), ...(testPlugins ? [(0, _path.resolve)(rootDir, 'test/analytics/__fixtures__/plugins'), (0, _path.resolve)(rootDir, 'test/plugin_functional/plugins'), (0, _path.resolve)(rootDir, 'test/interpreter_functional/plugins'), (0, _path.resolve)(rootDir, 'test/common/fixtures/plugins')] : []), ...(testPlugins && !oss ? [(0, _path.resolve)(rootDir, 'x-pack/test/plugin_functional/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/functional_with_es_ssl/fixtures/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/alerting_api_integration/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/plugin_api_integration/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/plugin_api_perf/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/licensing_plugin/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/usage_collection/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/security_functional/fixtures/common')] : [])]; + return [(0, _path.resolve)(rootDir, 'src', 'plugins'), ...(oss ? [] : [(0, _path.resolve)(rootDir, 'x-pack', 'plugins')]), (0, _path.resolve)(rootDir, 'plugins'), ...(examples ? [(0, _path.resolve)(rootDir, 'examples')] : []), ...(examples && !oss ? [(0, _path.resolve)(rootDir, 'x-pack', 'examples')] : []), (0, _path.resolve)(rootDir, '..', 'kibana-extra'), ...(testPlugins ? [(0, _path.resolve)(rootDir, 'test/analytics/fixtures/plugins'), (0, _path.resolve)(rootDir, 'test/plugin_functional/plugins'), (0, _path.resolve)(rootDir, 'test/interpreter_functional/plugins'), (0, _path.resolve)(rootDir, 'test/common/fixtures/plugins')] : []), ...(testPlugins && !oss ? [(0, _path.resolve)(rootDir, 'x-pack/test/plugin_functional/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/functional_with_es_ssl/fixtures/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/alerting_api_integration/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/plugin_api_integration/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/plugin_api_perf/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/licensing_plugin/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/usage_collection/plugins'), (0, _path.resolve)(rootDir, 'x-pack/test/security_functional/fixtures/common')] : [])]; } /***/ }), diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index 520b96d261fd9..ff9ae42d633fb 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -89,6 +89,7 @@ export const PROJECTS = [ 'x-pack/plugins/*/tsconfig.json', 'examples/*/tsconfig.json', 'x-pack/examples/*/tsconfig.json', + 'test/analytics/fixtures/plugins/*/tsconfig.json', 'test/plugin_functional/plugins/*/tsconfig.json', 'test/interpreter_functional/plugins/*/tsconfig.json', 'test/server_integration/__fixtures__/plugins/*/tsconfig.json', diff --git a/test/analytics/README.md b/test/analytics/README.md index 72a03cd9dac93..cc2bd39297059 100644 --- a/test/analytics/README.md +++ b/test/analytics/README.md @@ -14,8 +14,10 @@ There are 2 FTR helpers to allow you to retrieve the generated events: The API is the same for both of them: ```typescript // To retrieve 2 events of type "my-event-type" -const events = await getService('kibana_ebt_ui').getEvents(2, ['my-event-type']); +const events = await getService('kibana_ebt_ui').getEvents(2, { eventTypes: ['my-event-type'] }); expect(events).to... ``` -If you are reusing these helpers in another suite, please remember to make sure to optIn via `await getService('kibana_ebt_ui').setOptIn(true);` \ No newline at end of file +If you are reusing these helpers in another suite, please remember to make sure to optIn via `await getService('kibana_ebt_ui').setOptIn(true);` + +Refer to [`EBTHelpersContract`](./fixtures/plugins/analytics_ftr_helpers/common/types.ts#:~:text=EBTHelpersContract) for more details about the existing APIs and all the options they accept. \ No newline at end of file diff --git a/test/analytics/config.ts b/test/analytics/config.ts index 842187f7de393..307ed42a439a7 100644 --- a/test/analytics/config.ts +++ b/test/analytics/config.ts @@ -35,8 +35,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { serverArgs: [ ...functionalConfig.get('kbnTestServer.serverArgs'), '--telemetry.optIn=true', - `--plugin-path=${path.resolve(__dirname, './__fixtures__/plugins/analytics_plugin_a')}`, - `--plugin-path=${path.resolve(__dirname, './__fixtures__/plugins/analytics_ftr_helpers')}`, + `--plugin-path=${path.resolve(__dirname, './fixtures/plugins/analytics_plugin_a')}`, + `--plugin-path=${path.resolve(__dirname, './fixtures/plugins/analytics_ftr_helpers')}`, ], }, }; diff --git a/test/analytics/fixtures/plugins/analytics_ftr_helpers/common/fetch_events.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/common/fetch_events.ts new file mode 100644 index 0000000000000..9977fd618c171 --- /dev/null +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/common/fetch_events.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + filter, + firstValueFrom, + map, + NEVER, + type Observable, + take, + takeUntil, + timer, + toArray, +} from 'rxjs'; +import type { Event } from '@kbn/analytics-client'; +import type { GetEventsOptions } from './types'; + +export async function fetchEvents( + events$: Observable, + takeNumberOfEvents: number, + options: GetEventsOptions = {} +): Promise { + const { eventTypes = [], withTimeoutMs, fromTimestamp } = options; + + const filteredEvents$ = events$.pipe( + filter((event) => { + if (eventTypes.length > 0) { + return eventTypes.includes(event.event_type); + } + return true; + }), + filter((event) => { + if (fromTimestamp) { + return new Date(event.timestamp).getTime() - new Date(fromTimestamp).getTime() >= 0; + } + return true; + }) + ); + + return firstValueFrom( + filteredEvents$.pipe( + take(takeNumberOfEvents), + // If timeout is specified, close the subscriber when the timeout occurs + takeUntil(withTimeoutMs ? timer(withTimeoutMs) : NEVER), + toArray(), + // Sorting the events by timestamp... on CI it's happening an event may occur while the client is still forwarding the early ones... + map((_events) => + _events.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()) + ) + ) + ); +} diff --git a/test/analytics/fixtures/plugins/analytics_ftr_helpers/common/types.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/common/types.ts new file mode 100644 index 0000000000000..019636dc5893c --- /dev/null +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/common/types.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Event, EventType } from '@kbn/analytics-client'; + +export interface GetEventsOptions { + /** + * eventTypes (optional) array of event types to return + */ + eventTypes?: EventType[]; + /** + * withTimeoutMs (optional) if specified, the method returns all the events received when the first occurs: + * - The number of received events match `takeNumberOfEvents`. + * - The number of ms in `withTimeoutMs` has elapsed. + */ + withTimeoutMs?: number; + /** + * fromTimestamp (optional) if specified, only the events that are greater or equal to the provided timestamp will be returned. + * @remarks Useful when we need to retrieve the events after a specific action, and we don't care about anything prior to that. + */ + fromTimestamp?: string; +} + +export interface EBTHelpersContract { + /** + * Change the opt-in state of the Kibana EBT client. + * @param optIn `true` to opt-in, `false` to opt-out. + */ + setOptIn: (optIn: boolean) => void; + /** + * Returns the first N number of events of the specified types. + * @param takeNumberOfEvents - number of events to return + * @param options (optional) list of options to filter events or for advanced usage of the API {@link GetEventsOptions}. + */ + getEvents: (takeNumberOfEvents: number, options?: GetEventsOptions) => Promise; + /** + * Count the number of events that match the filters. + * @param options list of options to filter the events {@link GetEventsOptions}. `withTimeoutMs` is required in this API. + */ + getEventCount: ( + options: Required> & + Omit + ) => Promise; +} diff --git a/test/analytics/fixtures/plugins/analytics_ftr_helpers/jest.config.js b/test/analytics/fixtures/plugins/analytics_ftr_helpers/jest.config.js new file mode 100644 index 0000000000000..ffbc666f750f0 --- /dev/null +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/jest.config.js @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/test/analytics/fixtures/plugins/analytics_ftr_helpers'], + coverageDirectory: + '/target/kibana-coverage/jest/test/analytics/fixtures/plugins/analytics_ftr_helpers', + coverageReporters: ['text', 'html'], + collectCoverageFrom: [ + '/test/analytics/fixtures/plugins/analytics_ftr_helpers/{common,public,server}/**/*.{ts,tsx}', + ], +}; diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/kibana.json b/test/analytics/fixtures/plugins/analytics_ftr_helpers/kibana.json similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/kibana.json rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/kibana.json diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/package.json b/test/analytics/fixtures/plugins/analytics_ftr_helpers/package.json similarity index 80% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/package.json rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/package.json index c0a0c5082d1d3..77535df59ff74 100644 --- a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/package.json +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/package.json @@ -1,7 +1,7 @@ { "name": "analytics_ftr_helpers", "version": "1.0.0", - "main": "target/test/analytics/__fixtures__/plugins/analytics_ftr_helpers", + "main": "target/test/analytics/fixtures/plugins/analytics_ftr_helpers", "kibana": { "version": "kibana", "templateVersion": "1.0.0" diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/custom_shipper.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/custom_shipper.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/custom_shipper.ts rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/public/custom_shipper.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/index.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/index.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/index.ts rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/public/index.ts diff --git a/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/plugin.test.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/plugin.test.ts new file mode 100644 index 0000000000000..bf7eb7fda9365 --- /dev/null +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/plugin.test.ts @@ -0,0 +1,133 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ReplaySubject } from 'rxjs'; +import type { AnalyticsServiceSetup, Event } from '@kbn/core/public'; +import { coreMock } from '@kbn/core/public/mocks'; + +// Importing types to have the window properties defined +import './types'; +import { AnalyticsFTRHelpers } from './plugin'; +import { withTimeout } from '@kbn/std'; + +describe('AnalyticsFTRHelpers', () => { + let plugin: AnalyticsFTRHelpers; + let events$: ReplaySubject; + let analyticsMock: jest.Mocked; + + beforeEach(() => { + plugin = new AnalyticsFTRHelpers(); + // eslint-disable-next-line dot-notation + events$ = plugin['events$']; + const coreSetup = coreMock.createSetup(); + analyticsMock = coreSetup.analytics; + plugin.setup(coreSetup); + }); + + describe('setOptIn', () => { + test.each([true, false])('sets optIn value to %p', (optInValue) => { + window.__analytics_ftr_helpers__.setOptIn(optInValue); + expect(analyticsMock.optIn).toHaveBeenCalledWith({ global: { enabled: optInValue } }); + }); + }); + + describe('getEvents', () => { + const event: Event = { + timestamp: new Date().toISOString(), + event_type: 'test-event', + context: {}, + properties: {}, + }; + + test('should return any previously enqueued events as long as they match the required number of events', async () => { + // 3 enqueued events + const events = new Array(3).fill(event); + events.forEach((ev) => events$.next(ev)); + + await expect(window.__analytics_ftr_helpers__.getEvents(3)).resolves.toEqual(events); + }); + + test('should await until it matches the required number of events', async () => { + // 3 enqueued events + const events = new Array(3).fill(event); + events.forEach((ev) => events$.next(ev)); + + const getEventsPromise = window.__analytics_ftr_helpers__.getEvents(4); + + await expect(withTimeout({ promise: getEventsPromise, timeoutMs: 1000 })).resolves.toEqual({ + timedout: true, + }); + + // we are not filtering in the call by event type, so it should resolve as well + const anotherEvent = { ...event, event_type: 'another-test-event' }; + events$.next(anotherEvent); + + await expect(getEventsPromise).resolves.toEqual([...events, anotherEvent]); + }); + + test('should await until it times out', async () => { + // 3 enqueued events + const events = new Array(3).fill(event); + events.forEach((ev) => events$.next(ev)); + + // expecting 4 with timeout of 1.5s + const getEventsPromise = window.__analytics_ftr_helpers__.getEvents(4, { + withTimeoutMs: 1500, + }); + + // after 1 second it still doesn't emit + await expect(withTimeout({ promise: getEventsPromise, timeoutMs: 1000 })).resolves.toEqual({ + timedout: true, + }); + + // it emits 3 events at some point + await expect(getEventsPromise).resolves.toEqual(events); + }); + + test('should filter by event-types when provided', async () => { + // 3 enqueued events + const events = [ + { ...event, event_type: 'one-test-event' }, + { ...event, event_type: 'another-test-event' }, + { ...event, event_type: 'skipped-test-event' }, + { ...event, event_type: 'another-test-event' }, + ]; + events.forEach((ev) => events$.next(ev)); + + await expect( + window.__analytics_ftr_helpers__.getEvents(3, { + eventTypes: ['one-test-event', 'another-test-event'], + }) + ).resolves.toEqual([ + { ...event, event_type: 'one-test-event' }, + { ...event, event_type: 'another-test-event' }, + { ...event, event_type: 'another-test-event' }, + ]); + }); + + test('should filter by timestamp when provided', async () => { + // 3 enqueued events + const events = [ + { ...event, timestamp: '2022-01-10T00:00:00.000Z' }, + { ...event, timestamp: '2022-03-10T00:00:00.000Z' }, + { ...event, timestamp: '2022-06-10T00:00:00.000Z' }, + ]; + events.forEach((ev) => events$.next(ev)); + + await expect( + window.__analytics_ftr_helpers__.getEvents(2, { + eventTypes: [event.event_type], + fromTimestamp: '2022-03-10T00:00:00.000Z', + }) + ).resolves.toEqual([ + { ...event, timestamp: '2022-03-10T00:00:00.000Z' }, + { ...event, timestamp: '2022-06-10T00:00:00.000Z' }, + ]); + }); + }); +}); diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/plugin.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/plugin.ts similarity index 52% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/plugin.ts rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/public/plugin.ts index 9b1e2190c29aa..125f712da9423 100644 --- a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/plugin.ts +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/plugin.ts @@ -6,10 +6,11 @@ * Side Public License, v 1. */ -import { ReplaySubject, firstValueFrom, filter, take, toArray, map } from 'rxjs'; +import { ReplaySubject } from 'rxjs'; import type { Plugin, CoreSetup, Event } from '@kbn/core/public'; import { CustomShipper } from './custom_shipper'; import './types'; +import { fetchEvents } from '../common/fetch_events'; export class AnalyticsFTRHelpers implements Plugin { private readonly events$ = new ReplaySubject(); @@ -21,25 +22,10 @@ export class AnalyticsFTRHelpers implements Plugin { setOptIn(optIn: boolean) { analytics.optIn({ global: { enabled: optIn } }); }, - getEvents: async (takeNumberOfEvents, eventTypes = []) => - firstValueFrom( - this.events$.pipe( - filter((event) => { - if (eventTypes.length > 0) { - return eventTypes.includes(event.event_type); - } - return true; - }), - take(takeNumberOfEvents), - toArray(), - // Sorting the events by timestamp... on CI it's happening an event may occur while the client is still forwarding the early ones... - map((_events) => - _events.sort( - (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() - ) - ) - ) - ), + getEvents: async (takeNumberOfEvents, options) => + fetchEvents(this.events$, takeNumberOfEvents, options), + getEventCount: async (options) => + (await fetchEvents(this.events$, Number.MAX_SAFE_INTEGER, options)).length, }; } public start() {} diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/types.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/types.ts similarity index 63% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/types.ts rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/public/types.ts index 62e43502fb100..c9348a1fd2859 100644 --- a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/types.ts +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/public/types.ts @@ -6,13 +6,10 @@ * Side Public License, v 1. */ -import type { Event, EventType } from '@kbn/core/public'; +import { EBTHelpersContract } from '../common/types'; declare global { interface Window { - __analytics_ftr_helpers__: { - setOptIn: (optIn: boolean) => void; - getEvents: (takeNumberOfEvents: number, eventTypes?: EventType[]) => Promise; - }; + __analytics_ftr_helpers__: EBTHelpersContract; } } diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/custom_shipper.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/server/custom_shipper.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/custom_shipper.ts rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/server/custom_shipper.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/index.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/server/index.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/index.ts rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/server/index.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/plugin.ts b/test/analytics/fixtures/plugins/analytics_ftr_helpers/server/plugin.ts similarity index 64% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/plugin.ts rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/server/plugin.ts index 22bc67c805ca9..88cacd2bfd36d 100644 --- a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/plugin.ts +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/server/plugin.ts @@ -6,9 +6,10 @@ * Side Public License, v 1. */ -import { firstValueFrom, ReplaySubject, filter, take, toArray, map } from 'rxjs'; +import { ReplaySubject } from 'rxjs'; import { schema } from '@kbn/config-schema'; import type { Plugin, CoreSetup, Event } from '@kbn/core/server'; +import { fetchEvents } from '../common/fetch_events'; import { CustomShipper } from './custom_shipper'; export class AnalyticsFTRHelpers implements Plugin { @@ -45,34 +46,34 @@ export class AnalyticsFTRHelpers implements Plugin { query: schema.object({ takeNumberOfEvents: schema.number({ min: 1 }), eventTypes: schema.arrayOf(schema.string()), + withTimeoutMs: schema.maybe(schema.number()), + fromTimestamp: schema.maybe(schema.string()), }), }, }, async (context, req, res) => { - const { takeNumberOfEvents, eventTypes } = req.query; - - const events = await firstValueFrom( - events$.pipe( - filter((event) => { - if (eventTypes.length > 0) { - return eventTypes.includes(event.event_type); - } - return true; - }), - take(takeNumberOfEvents), - toArray(), - // Sorting the events by timestamp... on CI it's happening an event may occur while the client is still forwarding the early ones... - map((_events) => - _events.sort( - (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() - ) - ) - ) - ); - + const { takeNumberOfEvents, ...options } = req.query; + const events = await fetchEvents(events$, takeNumberOfEvents, options); return res.ok({ body: events }); } ); + + router.get( + { + path: '/internal/analytics_ftr_helpers/count_events', + validate: { + query: schema.object({ + eventTypes: schema.arrayOf(schema.string()), + withTimeoutMs: schema.number(), + fromTimestamp: schema.maybe(schema.string()), + }), + }, + }, + async (context, req, res) => { + const events = await fetchEvents(events$, Number.MAX_SAFE_INTEGER, req.query); + return res.ok({ body: { count: events.length } }); + } + ); } public start() {} diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/tsconfig.json b/test/analytics/fixtures/plugins/analytics_ftr_helpers/tsconfig.json similarity index 93% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/tsconfig.json rename to test/analytics/fixtures/plugins/analytics_ftr_helpers/tsconfig.json index d1faee2d113b6..c54e279cedf8c 100644 --- a/test/analytics/__fixtures__/plugins/analytics_plugin_a/tsconfig.json +++ b/test/analytics/fixtures/plugins/analytics_ftr_helpers/tsconfig.json @@ -5,6 +5,7 @@ }, "include": [ "index.ts", + "common/**/*.ts", "public/**/*.ts", "server/**/*.ts", "../../../../../typings/**/*", diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/kibana.json b/test/analytics/fixtures/plugins/analytics_plugin_a/kibana.json similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/kibana.json rename to test/analytics/fixtures/plugins/analytics_plugin_a/kibana.json diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/package.json b/test/analytics/fixtures/plugins/analytics_plugin_a/package.json similarity index 81% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/package.json rename to test/analytics/fixtures/plugins/analytics_plugin_a/package.json index dcb2fbcbe81d9..d49950be253e3 100644 --- a/test/analytics/__fixtures__/plugins/analytics_plugin_a/package.json +++ b/test/analytics/fixtures/plugins/analytics_plugin_a/package.json @@ -1,7 +1,7 @@ { "name": "analytics_plugin_a", "version": "1.0.0", - "main": "target/test/analytics/__fixtures__/plugins/analytics_plugin_a", + "main": "target/test/analytics/fixtures/plugins/analytics_plugin_a", "kibana": { "version": "kibana", "templateVersion": "1.0.0" diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/custom_shipper.ts b/test/analytics/fixtures/plugins/analytics_plugin_a/public/custom_shipper.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/public/custom_shipper.ts rename to test/analytics/fixtures/plugins/analytics_plugin_a/public/custom_shipper.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/index.ts b/test/analytics/fixtures/plugins/analytics_plugin_a/public/index.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/public/index.ts rename to test/analytics/fixtures/plugins/analytics_plugin_a/public/index.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/plugin.ts b/test/analytics/fixtures/plugins/analytics_plugin_a/public/plugin.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/public/plugin.ts rename to test/analytics/fixtures/plugins/analytics_plugin_a/public/plugin.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/types.ts b/test/analytics/fixtures/plugins/analytics_plugin_a/public/types.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/public/types.ts rename to test/analytics/fixtures/plugins/analytics_plugin_a/public/types.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/server/custom_shipper.ts b/test/analytics/fixtures/plugins/analytics_plugin_a/server/custom_shipper.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/server/custom_shipper.ts rename to test/analytics/fixtures/plugins/analytics_plugin_a/server/custom_shipper.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/server/index.ts b/test/analytics/fixtures/plugins/analytics_plugin_a/server/index.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/server/index.ts rename to test/analytics/fixtures/plugins/analytics_plugin_a/server/index.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/server/plugin.ts b/test/analytics/fixtures/plugins/analytics_plugin_a/server/plugin.ts similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_plugin_a/server/plugin.ts rename to test/analytics/fixtures/plugins/analytics_plugin_a/server/plugin.ts diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/tsconfig.json b/test/analytics/fixtures/plugins/analytics_plugin_a/tsconfig.json similarity index 100% rename from test/analytics/__fixtures__/plugins/analytics_ftr_helpers/tsconfig.json rename to test/analytics/fixtures/plugins/analytics_plugin_a/tsconfig.json diff --git a/test/analytics/jest.config.js b/test/analytics/jest.config.js new file mode 100644 index 0000000000000..0e9f9b9be251d --- /dev/null +++ b/test/analytics/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/test/analytics'], +}; diff --git a/test/analytics/services/kibana_ebt.ts b/test/analytics/services/kibana_ebt.ts index e8e47fcbb5abf..a7754a5a870ba 100644 --- a/test/analytics/services/kibana_ebt.ts +++ b/test/analytics/services/kibana_ebt.ts @@ -6,10 +6,11 @@ * Side Public License, v 1. */ -import { FtrProviderContext } from '../../functional/ftr_provider_context'; import '@kbn/analytics-ftr-helpers-plugin/public/types'; +import type { EBTHelpersContract } from '@kbn/analytics-ftr-helpers-plugin/common/types'; +import type { FtrProviderContext } from '../../functional/ftr_provider_context'; -export function KibanaEBTServerProvider({ getService }: FtrProviderContext) { +export function KibanaEBTServerProvider({ getService }: FtrProviderContext): EBTHelpersContract { const supertest = getService('supertest'); const setOptIn = async (optIn: boolean) => { @@ -21,30 +22,42 @@ export function KibanaEBTServerProvider({ getService }: FtrProviderContext) { }; return { - /** - * Change the opt-in state of the Kibana EBT client. - * @param optIn `true` to opt-in, `false` to opt-out. - */ setOptIn, - /** - * Returns the last events of the specified types. - * @param takeNumberOfEvents - number of events to return - * @param eventTypes (Optional) array of event types to return - */ - getEvents: async (takeNumberOfEvents: number, eventTypes: string[] = []) => { + getEvents: async ( + takeNumberOfEvents, + { eventTypes = [], withTimeoutMs, fromTimestamp } = {} + ) => { await setOptIn(true); const resp = await supertest .get(`/internal/analytics_ftr_helpers/events`) - .query({ takeNumberOfEvents, eventTypes: JSON.stringify(eventTypes) }) + .query({ + takeNumberOfEvents, + eventTypes: JSON.stringify(eventTypes), + withTimeoutMs, + fromTimestamp, + }) .set('kbn-xsrf', 'xxx') .expect(200); return resp.body; }, + getEventCount: async ({ eventTypes = [], withTimeoutMs, fromTimestamp }) => { + await setOptIn(true); + const resp = await supertest + .get(`/internal/analytics_ftr_helpers/count_events`) + .query({ eventTypes: JSON.stringify(eventTypes), withTimeoutMs, fromTimestamp }) + .set('kbn-xsrf', 'xxx') + .expect(200); + + return resp.body.count; + }, }; } -export function KibanaEBTUIProvider({ getService, getPageObjects }: FtrProviderContext) { +export function KibanaEBTUIProvider({ + getService, + getPageObjects, +}: FtrProviderContext): EBTHelpersContract { const { common } = getPageObjects(['common']); const browser = getService('browser'); @@ -53,30 +66,24 @@ export function KibanaEBTUIProvider({ getService, getPageObjects }: FtrProviderC }; return { - /** - * Change the opt-in state of the Kibana EBT client. - * @param optIn `true` to opt-in, `false` to opt-out. - */ - setOptIn: async (optIn: boolean) => { + setOptIn: async (optIn) => { await common.navigateToApp('home'); await setOptIn(optIn); }, - /** - * Returns the last events of the specified types. - * @param numberOfEvents - number of events to return - * @param eventTypes (Optional) array of event types to return - */ - getEvents: async (numberOfEvents: number, eventTypes: string[] = []) => { + getEvents: async (numberOfEvents, options) => { + await setOptIn(true); + return await browser.execute( + ({ numberOfEvents: _numberOfEvents, options: _options }) => + window.__analytics_ftr_helpers__.getEvents(_numberOfEvents, _options), + { numberOfEvents, options } + ); + }, + getEventCount: async (options) => { await setOptIn(true); - const events = await browser.execute( - ({ eventTypes: _eventTypes, numberOfEvents: _numberOfEvents }) => - window.__analytics_ftr_helpers__.getEvents(_numberOfEvents, _eventTypes), - { - eventTypes, - numberOfEvents, - } + return await browser.execute( + ({ options: _options }) => window.__analytics_ftr_helpers__.getEventCount(_options), + { options } ); - return events; }, }; } diff --git a/test/analytics/tests/analytics_from_the_browser.ts b/test/analytics/tests/analytics_from_the_browser.ts index a35842dc1a44a..d700465b1070b 100644 --- a/test/analytics/tests/analytics_from_the_browser.ts +++ b/test/analytics/tests/analytics_from_the_browser.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import type { Event, TelemetryCounter } from '@kbn/core/server'; -import type { Action } from '@kbn/analytics-plugin-a-plugin/server/custom_shipper'; +import type { Action } from '@kbn/analytics-plugin-a-plugin/public/custom_shipper'; import type { FtrProviderContext } from '../services'; import '@kbn/analytics-plugin-a-plugin/public/types'; @@ -146,7 +146,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(startEvent).to.be.greaterThan(setupEvent); // This helps us to also test the helpers - const events = await ebtUIHelper.getEvents(2, ['test-plugin-lifecycle']); + const events = await ebtUIHelper.getEvents(2, { eventTypes: ['test-plugin-lifecycle'] }); expect(events).to.eql([ { timestamp: reportTestPluginLifecycleEventsAction!.meta[setupEvent].timestamp, @@ -164,11 +164,45 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('it should extend the contexts with pid injected by "analytics_plugin_a"', async () => { - const [event] = await ebtUIHelper.getEvents(1, ['test-plugin-lifecycle']); + const [event] = await ebtUIHelper.getEvents(1, { eventTypes: ['test-plugin-lifecycle'] }); // Validating the remote user_agent because that's the only field that it's added by the FTR plugin. expect(event.context).to.have.property('user_agent'); expect(event.context.user_agent).to.be.a('string'); }); + + describe('Test helpers capabilities', () => { + it('should return the count of the events', async () => { + const eventCount = await ebtUIHelper.getEventCount({ + withTimeoutMs: 500, + eventTypes: ['test-plugin-lifecycle'], + }); + expect(eventCount).to.be(2); + }); + + it('should return 0 events when filtering by timestamp', async () => { + const eventCount = await ebtUIHelper.getEventCount({ + withTimeoutMs: 500, + eventTypes: ['test-plugin-lifecycle'], + fromTimestamp: new Date().toISOString(), + }); + expect(eventCount).to.be(0); + }); + + it('should return 1 event when filtering by the latest timestamp', async () => { + const events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['test-plugin-lifecycle'], + withTimeoutMs: 500, + }); + expect(events.length).to.be.greaterThan(0); + const lastEvent = events[events.length - 1]; + const eventCount = await ebtUIHelper.getEventCount({ + withTimeoutMs: 500, + eventTypes: ['test-plugin-lifecycle'], + fromTimestamp: lastEvent.timestamp, + }); + expect(eventCount).to.be(1); + }); + }); }); }); } diff --git a/test/analytics/tests/analytics_from_the_server.ts b/test/analytics/tests/analytics_from_the_server.ts index d33c66d48463b..7b208f955ee82 100644 --- a/test/analytics/tests/analytics_from_the_server.ts +++ b/test/analytics/tests/analytics_from_the_server.ts @@ -139,7 +139,9 @@ export default function ({ getService }: FtrProviderContext) { expect(startEvent).to.be.greaterThan(setupEvent); // This helps us to also test the helpers - const events = await ebtServerHelper.getEvents(2, ['test-plugin-lifecycle']); + const events = await ebtServerHelper.getEvents(2, { + eventTypes: ['test-plugin-lifecycle'], + }); expect(events).to.eql([ { timestamp: reportTestPluginLifecycleEventsAction!.meta[setupEvent].timestamp, @@ -157,11 +159,46 @@ export default function ({ getService }: FtrProviderContext) { }); it('it should extend the contexts with pid injected by "analytics_plugin_a"', async () => { - const [event] = await ebtServerHelper.getEvents(1, ['test-plugin-lifecycle']); + const [event] = await ebtServerHelper.getEvents(1, { + eventTypes: ['test-plugin-lifecycle'], + }); // Validating the remote PID because that's the only field that it's added by the FTR plugin. expect(event.context).to.have.property('pid'); expect(event.context.pid).to.be.a('number'); }); + + describe('Test helpers capabilities', () => { + it('should return the count of the events', async () => { + const eventCount = await ebtServerHelper.getEventCount({ + withTimeoutMs: 500, + eventTypes: ['test-plugin-lifecycle'], + }); + expect(eventCount).to.be(2); + }); + + it('should return 0 events when filtering by timestamp', async () => { + const eventCount = await ebtServerHelper.getEventCount({ + withTimeoutMs: 500, + eventTypes: ['test-plugin-lifecycle'], + fromTimestamp: new Date().toISOString(), + }); + expect(eventCount).to.be(0); + }); + it('should return 1 event when filtering by the latest timestamp', async () => { + const events = await ebtServerHelper.getEvents(Number.MAX_SAFE_INTEGER, { + withTimeoutMs: 500, + eventTypes: ['test-plugin-lifecycle'], + }); + expect(events.length).to.be.greaterThan(0); + const lastEvent = events[events.length - 1]; + const eventCount = await ebtServerHelper.getEventCount({ + withTimeoutMs: 500, + eventTypes: ['test-plugin-lifecycle'], + fromTimestamp: lastEvent.timestamp, + }); + expect(eventCount).to.be(1); + }); + }); }); }); } diff --git a/test/analytics/tests/instrumented_events/from_the_browser/click.ts b/test/analytics/tests/instrumented_events/from_the_browser/click.ts index 9dbd864f98af7..1063e1cd9fd62 100644 --- a/test/analytics/tests/instrumented_events/from_the_browser/click.ts +++ b/test/analytics/tests/instrumented_events/from_the_browser/click.ts @@ -21,7 +21,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should emit a "click" event', async () => { - const [event] = await ebtUIHelper.getEvents(1, ['click']); + const [event] = await ebtUIHelper.getEvents(1, { eventTypes: ['click'] }); expect(event.event_type).to.eql('click'); expect(event.properties.target).to.be.an('array'); const targets = event.properties.target as string[]; diff --git a/test/analytics/tests/instrumented_events/from_the_browser/core_context_providers.ts b/test/analytics/tests/instrumented_events/from_the_browser/core_context_providers.ts index 1f688fbac0f17..6543b3c7955ef 100644 --- a/test/analytics/tests/instrumented_events/from_the_browser/core_context_providers.ts +++ b/test/analytics/tests/instrumented_events/from_the_browser/core_context_providers.ts @@ -19,7 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { let event: Event; before(async () => { await common.navigateToApp('home'); - [event] = await ebtUIHelper.getEvents(1, ['Loaded Kibana']); // Get the loaded Kibana event + [event] = await ebtUIHelper.getEvents(1, { eventTypes: ['Loaded Kibana'] }); // Get the loaded Kibana event }); it('should have the properties provided by the "cluster info" context provider', () => { @@ -74,7 +74,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should have the properties provided by the "license info" context provider', async () => { await common.clickAndValidate('kibanaChrome', 'kibanaChrome'); - [event] = await ebtUIHelper.getEvents(1, ['click']); // Get a later event to ensure license has been obtained already. + [event] = await ebtUIHelper.getEvents(1, { eventTypes: ['click'] }); // Get a later event to ensure license has been obtained already. expect(event.context).to.have.property('license_id'); expect(event.context.license_id).to.be.a('string'); expect(event.context).to.have.property('license_status'); diff --git a/test/analytics/tests/instrumented_events/from_the_browser/loaded_kibana.ts b/test/analytics/tests/instrumented_events/from_the_browser/loaded_kibana.ts index 15558567ba37f..7ed47db35cbeb 100644 --- a/test/analytics/tests/instrumented_events/from_the_browser/loaded_kibana.ts +++ b/test/analytics/tests/instrumented_events/from_the_browser/loaded_kibana.ts @@ -20,7 +20,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should emit the "Loaded Kibana" event', async () => { - const [event] = await ebtUIHelper.getEvents(1, ['Loaded Kibana']); + const [event] = await ebtUIHelper.getEvents(1, { eventTypes: ['Loaded Kibana'] }); expect(event.event_type).to.eql('Loaded Kibana'); expect(event.properties).to.have.property('kibana_version'); expect(event.properties.kibana_version).to.be.a('string'); diff --git a/test/analytics/tests/instrumented_events/from_the_server/core_context_providers.ts b/test/analytics/tests/instrumented_events/from_the_server/core_context_providers.ts index adf0c65445dd3..9a694c38b8b40 100644 --- a/test/analytics/tests/instrumented_events/from_the_server/core_context_providers.ts +++ b/test/analytics/tests/instrumented_events/from_the_server/core_context_providers.ts @@ -20,7 +20,9 @@ export default function ({ getService }: FtrProviderContext) { let i = 2; do { // Wait until we get a GREEN "status_changed" event. At that point all the context providers should be set up. - const events = await ebtServerHelper.getEvents(i, ['core-overall_status_changed']); + const events = await ebtServerHelper.getEvents(i, { + eventTypes: ['core-overall_status_changed'], + }); event = events[i - 1]; i++; } while (event.properties.overall_status_level !== 'available'); diff --git a/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts b/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts index 1b20d6b9b21dc..07c03465f6c27 100644 --- a/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts +++ b/test/analytics/tests/instrumented_events/from_the_server/core_overall_status_changed.ts @@ -18,9 +18,9 @@ export default function ({ getService }: FtrProviderContext) { let secondEvent: Event; before(async () => { - [initialEvent, secondEvent] = await ebtServerHelper.getEvents(2, [ - 'core-overall_status_changed', - ]); + [initialEvent, secondEvent] = await ebtServerHelper.getEvents(2, { + eventTypes: ['core-overall_status_changed'], + }); }); it('should emit the initial "degraded" event with the context set to `initializing`', () => { diff --git a/test/analytics/tests/instrumented_events/from_the_server/kibana_started.ts b/test/analytics/tests/instrumented_events/from_the_server/kibana_started.ts index 526dfe8d72a21..5380d4e392e52 100644 --- a/test/analytics/tests/instrumented_events/from_the_server/kibana_started.ts +++ b/test/analytics/tests/instrumented_events/from_the_server/kibana_started.ts @@ -14,16 +14,20 @@ export default function ({ getService }: FtrProviderContext) { describe('kibana_started', () => { it('should emit the "kibana_started" event', async () => { - const [event] = await ebtServerHelper.getEvents(1, ['kibana_started']); + const [event] = await ebtServerHelper.getEvents(1, { eventTypes: ['kibana_started'] }); expect(event.event_type).to.eql('kibana_started'); - expect(event.properties.uptime_per_step.constructor.start).to.be.a('number'); - expect(event.properties.uptime_per_step.constructor.end).to.be.a('number'); - expect(event.properties.uptime_per_step.preboot.start).to.be.a('number'); - expect(event.properties.uptime_per_step.preboot.end).to.be.a('number'); - expect(event.properties.uptime_per_step.setup.start).to.be.a('number'); - expect(event.properties.uptime_per_step.setup.end).to.be.a('number'); - expect(event.properties.uptime_per_step.start.start).to.be.a('number'); - expect(event.properties.uptime_per_step.start.end).to.be.a('number'); + const uptimePerStep = event.properties.uptime_per_step as Record< + 'constructor' | 'preboot' | 'setup' | 'start', + Record<'start' | 'end', number> + >; + expect(uptimePerStep.constructor.start).to.be.a('number'); + expect(uptimePerStep.constructor.end).to.be.a('number'); + expect(uptimePerStep.preboot.start).to.be.a('number'); + expect(uptimePerStep.preboot.end).to.be.a('number'); + expect(uptimePerStep.setup.start).to.be.a('number'); + expect(uptimePerStep.setup.end).to.be.a('number'); + expect(uptimePerStep.start.start).to.be.a('number'); + expect(uptimePerStep.start.end).to.be.a('number'); }); }); } diff --git a/test/tsconfig.json b/test/tsconfig.json index 61a26eb709df3..2df2827807972 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -6,7 +6,7 @@ "declaration": true, "declarationMap": true, "types": [ - "node", + "node", "@emotion/react/types/css-prop", "@kbn/ambient-ui-types", ] @@ -22,7 +22,7 @@ ], "exclude": [ "target/**/*", - "analytics/__fixtures__/plugins/**/*", + "analytics/fixtures/plugins/**/*", "interpreter_functional/plugins/**/*", "plugin_functional/plugins/**/*", "server_integration/__fixtures__/plugins/**/*", @@ -59,8 +59,8 @@ { "path": "../src/plugins/usage_collection/tsconfig.json" }, { "path": "../src/plugins/data_view_management/tsconfig.json" }, { "path": "../src/plugins/visualizations/tsconfig.json" }, - { "path": "analytics/__fixtures__/plugins/analytics_ftr_helpers/tsconfig.json"}, - { "path": "analytics/__fixtures__/plugins/analytics_plugin_a/tsconfig.json"}, + { "path": "analytics/fixtures/plugins/analytics_ftr_helpers/tsconfig.json"}, + { "path": "analytics/fixtures/plugins/analytics_plugin_a/tsconfig.json"}, { "path": "interactive_setup_api_integration/fixtures/test_endpoints/tsconfig.json" }, { "path": "plugin_functional/plugins/core_app_status/tsconfig.json" }, { "path": "plugin_functional/plugins/core_provider_plugin/tsconfig.json" }, diff --git a/tsconfig.base.json b/tsconfig.base.json index 32bc0976bc0a2..f93820ce835fa 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -191,10 +191,10 @@ "@kbn/vis-type-xy-plugin/*": ["src/plugins/vis_types/xy/*"], "@kbn/visualizations-plugin": ["src/plugins/visualizations"], "@kbn/visualizations-plugin/*": ["src/plugins/visualizations/*"], - "@kbn/analytics-ftr-helpers-plugin": ["test/analytics/__fixtures__/plugins/analytics_ftr_helpers"], - "@kbn/analytics-ftr-helpers-plugin/*": ["test/analytics/__fixtures__/plugins/analytics_ftr_helpers/*"], - "@kbn/analytics-plugin-a-plugin": ["test/analytics/__fixtures__/plugins/analytics_plugin_a"], - "@kbn/analytics-plugin-a-plugin/*": ["test/analytics/__fixtures__/plugins/analytics_plugin_a/*"], + "@kbn/analytics-ftr-helpers-plugin": ["test/analytics/fixtures/plugins/analytics_ftr_helpers"], + "@kbn/analytics-ftr-helpers-plugin/*": ["test/analytics/fixtures/plugins/analytics_ftr_helpers/*"], + "@kbn/analytics-plugin-a-plugin": ["test/analytics/fixtures/plugins/analytics_plugin_a"], + "@kbn/analytics-plugin-a-plugin/*": ["test/analytics/fixtures/plugins/analytics_plugin_a/*"], "@kbn/coverage-fixtures-plugin": ["test/common/fixtures/plugins/coverage"], "@kbn/coverage-fixtures-plugin/*": ["test/common/fixtures/plugins/coverage/*"], "@kbn/newsfeed-fixtures-plugin": ["test/common/fixtures/plugins/newsfeed"], From d3756a10c18ec011f52369fb3129c33d189f064b Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Wed, 29 Jun 2022 14:47:33 +0200 Subject: [PATCH 06/10] Update failed migration roll back instructions (#135006) --- .../setup/upgrade/rollback-migration.asciidoc | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/setup/upgrade/rollback-migration.asciidoc b/docs/setup/upgrade/rollback-migration.asciidoc index c0cb126b37825..6415a7a62a71a 100644 --- a/docs/setup/upgrade/rollback-migration.asciidoc +++ b/docs/setup/upgrade/rollback-migration.asciidoc @@ -10,26 +10,31 @@ WARNING: Before you roll back {kib}, ensure that the version you want to roll ba your {es} cluster. If the version you want to roll back to is not compatible, you must also rollback {es}. Any changes made after an upgrade are lost when you roll back to a previous version. -To roll back after a failed upgrade migration, you must also rollback the saved object indices to be compatible with the previous {kib} version. +To roll back after a failed upgrade migration, you must also roll back the {kib} feature state to be compatible with the previous {kib} version. [float] -==== Roll back by restoring a backup snapshot +==== Roll back by restoring the {kib} feature state from a snapshot . Before proceeding, {ref}/snapshots-take-snapshot.html[take a snapshot] that contains the `kibana` feature state. By default, snapshots include the `kibana` feature state. . To make sure no {kib} instances are performing an upgrade migration, shut down all {kib} instances. -. To delete all saved object indices, enter: +. {ref}/snapshots-restore-snapshot.html[Restore] the `kibana` feature state from a snapshot taken before the failed {kib} upgrade. The following {es} request will only restore the {kib} feature state + [source,sh] -------------------------------------------- -DELETE /.kibana* +POST _snapshot/my_repository/my_snapshot_2099.05.06/_restore +{ + "indices": "-*", <1> + "feature_states": ["kibana"] +} -------------------------------------------- - -. {ref}/snapshots-restore-snapshot.html[Restore] the `kibana` feature state from the snapshot. +<1> Exclude all indices and data streams from the restore operation to ensure that only the {kib} system indices included in the {kib} feature state will be restored. . Start all {kib} instances on the older version you want to rollback to. [float] -==== (Not recommended) Roll back without a backup snapshot +==== (Not supported) Roll back without a backup snapshot + +WARNING: Rolling back without a backup snapshot is not supported and will be removed in a future version of {kib}. . To make sure no {kib} instances are performing an upgrade migration, shut down all {kib} instances. . {ref}/snapshots-take-snapshot.html[Take a snapshot] that includes the `kibana` feature state. By default, snapshots include the `kibana` feature state. @@ -58,7 +63,7 @@ POST /.kibana_3/_aliases/.kibana + [source,sh] -------------------------------------------- -PPUT /.kibana,.kibana_task_manager/_settings {"index.blocks.write": false} +PUT /.kibana,.kibana_task_manager/_settings {"index.blocks.write": false} -------------------------------------------- . Start {kib} on the older version you want to roll back to. From d1ac92c56ca72fd8c3c59a14fbe863293dd5af1c Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Wed, 29 Jun 2022 15:03:14 +0200 Subject: [PATCH 07/10] Do not await for getOptInStatus() on stop() (#134735) * Do not await for getOptInStatus() on stop() * Fix incorrect comment * Make sure we call analytics.optIn() during setup() * Remove unused import * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * Add simple comment * Revert switchMap => exhaustMap to prevent memory leaks; move takeUntil after exhaustMap Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/telemetry/server/plugin.test.ts | 20 +++++++ src/plugins/telemetry/server/plugin.ts | 65 +++++++++++---------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/plugins/telemetry/server/plugin.test.ts b/src/plugins/telemetry/server/plugin.test.ts index 9f7d0cfcf812f..4cfdcfd1ba5ff 100644 --- a/src/plugins/telemetry/server/plugin.test.ts +++ b/src/plugins/telemetry/server/plugin.test.ts @@ -14,6 +14,26 @@ import { TelemetryPlugin } from './plugin'; describe('TelemetryPlugin', () => { describe('setup', () => { + describe('when initial config does not allow changing opt in status', () => { + it('calls analytics optIn', () => { + const initializerContext = coreMock.createPluginInitializerContext({ + optIn: true, + allowChangingOptInStatus: false, + }); + const coreSetupMock = coreMock.createSetup(); + + new TelemetryPlugin(initializerContext).setup(coreSetupMock, { + usageCollection: usageCollectionPluginMock.createSetupContract(), + telemetryCollectionManager: telemetryCollectionManagerPluginMock.createSetupContract(), + }); + + expect(coreSetupMock.analytics.optIn).toHaveBeenCalledTimes(1); + expect(coreSetupMock.analytics.optIn).toHaveBeenCalledWith({ + global: { enabled: true }, + }); + }); + }); + describe('EBT shipper registration', () => { it('registers the Server telemetry shipper', () => { const initializerContext = coreMock.createPluginInitializerContext(); diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index 6a02750f10bbe..cf2f7710e8729 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -7,16 +7,20 @@ */ import { URL } from 'url'; -import type { Observable } from 'rxjs'; import { - BehaviorSubject, + type Observable, + startWith, firstValueFrom, ReplaySubject, exhaustMap, timer, distinctUntilChanged, filter, + takeUntil, + tap, + shareReplay, } from 'rxjs'; + import { ElasticV3ServerShipper } from '@kbn/analytics-shippers-elastic-v3-server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; @@ -34,6 +38,7 @@ import type { } from '@kbn/core/server'; import type { SecurityPluginStart } from '@kbn/security-plugin/server'; import { SavedObjectsClient } from '@kbn/core/server'; + import { registerRoutes } from './routes'; import { registerCollection } from './telemetry_collection'; import { @@ -86,10 +91,10 @@ export class TelemetryPlugin implements Plugin; - private readonly isOptedIn$ = new BehaviorSubject(undefined); + private readonly isOptedIn$: Observable; + private isOptedIn?: boolean; private readonly isDev: boolean; private readonly fetcherTask: FetcherTask; - private optInPromise?: Promise; /** * @private Used to mark the completion of the old UI Settings migration */ @@ -105,19 +110,7 @@ export class TelemetryPlugin implements Plugin(1); - /** - * Poll for the opt-in status and update the `isOptedIn$` subject. - * @private - */ - private readonly optInPollerSubscription = timer(0, OPT_IN_POLL_INTERVAL_MS) - .pipe( - exhaustMap(() => { - this.optInPromise = this.getOptInStatus(); - return this.optInPromise; - }), - distinctUntilChanged() - ) - .subscribe((isOptedIn) => this.isOptedIn$.next(isOptedIn)); + private pluginStop$ = new ReplaySubject(1); private security?: SecurityPluginStart; @@ -134,17 +127,26 @@ export class TelemetryPlugin implements Plugin this.getOptInStatus()), + takeUntil(this.pluginStop$), + startWith(this.isOptedIn), + filter((isOptedIn): isOptedIn is boolean => typeof isOptedIn === 'boolean'), + distinctUntilChanged(), + tap((optedIn) => (this.isOptedIn = optedIn)), + shareReplay(1) + ); } public setup( { analytics, http, savedObjects }: CoreSetup, { usageCollection, telemetryCollectionManager }: TelemetryPluginsDepsSetup ): TelemetryPluginSetup { - if (this.isOptedIn$.value !== undefined) { - analytics.optIn({ global: { enabled: this.isOptedIn$.value } }); + if (this.isOptedIn !== undefined) { + analytics.optIn({ global: { enabled: this.isOptedIn } }); } const currentKibanaVersion = this.currentKibanaVersion; @@ -193,9 +195,7 @@ export class TelemetryPlugin implements Plugin typeof isOptedIn === 'boolean')) - .subscribe((isOptedIn) => analytics.optIn({ global: { enabled: isOptedIn } })); + this.isOptedIn$.subscribe((enabled) => analytics.optIn({ global: { enabled } })); const savedObjectsInternalRepository = savedObjects.createInternalRepository(); this.savedObjectsInternalRepository = savedObjectsInternalRepository; @@ -206,19 +206,22 @@ export class TelemetryPlugin implements Plugin this.isOptedIn$.value === true, + getIsOptedIn: async () => this.isOptedIn === true, }; } - public async stop() { - this.optInPollerSubscription.unsubscribe(); - this.isOptedIn$.complete(); + public stop() { + this.pluginStop$.next(); + this.pluginStop$.complete(); + this.savedObjectsInternalClient$.complete(); this.fetcherTask.stop(); - if (this.optInPromise) await this.optInPromise; } private async getOptInStatus(): Promise { - const internalRepositoryClient = await firstValueFrom(this.savedObjectsInternalClient$); + const internalRepositoryClient = await firstValueFrom(this.savedObjectsInternalClient$, { + defaultValue: undefined, + }); + if (!internalRepositoryClient) return; let telemetrySavedObject: TelemetrySavedObject | undefined; try { From b590240d93d7f4086644644e6c5aafcac4398db9 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 29 Jun 2022 15:08:36 +0200 Subject: [PATCH 08/10] fix styling issues (#135406) --- .../static/components/empty_placeholder.tsx | 19 +-- .../editor_frame/suggestion_panel.tsx | 2 +- .../workspace_panel/workspace_panel.tsx | 130 +++++++++--------- 3 files changed, 75 insertions(+), 76 deletions(-) diff --git a/src/plugins/charts/public/static/components/empty_placeholder.tsx b/src/plugins/charts/public/static/components/empty_placeholder.tsx index 15235acfeb2a7..17e87485379e8 100644 --- a/src/plugins/charts/public/static/components/empty_placeholder.tsx +++ b/src/plugins/charts/public/static/components/empty_placeholder.tsx @@ -34,16 +34,11 @@ export const EmptyPlaceholder = ({ dataTestSubj = 'emptyPlaceholder', className, }: EmptyPlaceholderProps) => ( - - - -

{message}

-
+
+ + + +

{message}

+
+
); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index c97e5232af898..e64cdd9bd33dc 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -146,7 +146,7 @@ const SuggestionPreview = ({
- -

- - {!expressionExists - ? i18n.translate('xpack.lens.editorFrame.emptyWorkspace', { - defaultMessage: 'Drop some fields here to start', - }) - : i18n.translate('xpack.lens.editorFrame.emptyWorkspaceSimple', { - defaultMessage: 'Drop field here', - })} - -

- {!expressionExists && ( - <> - -

- {i18n.translate('xpack.lens.editorFrame.emptyWorkspaceHeading', { - defaultMessage: 'Lens is the recommended editor for creating visualizations', - })} +

+ +

+ + {!expressionExists + ? i18n.translate('xpack.lens.editorFrame.emptyWorkspace', { + defaultMessage: 'Drop some fields here to start', + }) + : i18n.translate('xpack.lens.editorFrame.emptyWorkspaceSimple', { + defaultMessage: 'Drop field here', + })} + +

+ {!expressionExists && ( + <> + +

+ {i18n.translate('xpack.lens.editorFrame.emptyWorkspaceHeading', { + defaultMessage: 'Lens is the recommended editor for creating visualizations', + })} +

+
+

+ + {i18n.translate('xpack.lens.editorFrame.goToForums', { + defaultMessage: 'Make requests and give feedback', + })} +

- -

- - {i18n.translate('xpack.lens.editorFrame.goToForums', { - defaultMessage: 'Make requests and give feedback', - })} - -

- - )} + + )} +
); }; @@ -430,30 +432,32 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({ data-test-subj="workspace-apply-changes-prompt" size="s" > - {applyChangesString} -

- - {i18n.translate('xpack.lens.editorFrame.applyChangesWorkspacePrompt', { - defaultMessage: 'Apply changes to render visualization', - })} - -

-

- dispatchLens(applyChanges())} - data-test-subj="lnsApplyChanges__workspace" - > - {applyChangesString} - -

+
+ {applyChangesString} +

+ + {i18n.translate('xpack.lens.editorFrame.applyChangesWorkspacePrompt', { + defaultMessage: 'Apply changes to render visualization', + })} + +

+

+ dispatchLens(applyChanges())} + data-test-subj="lnsApplyChanges__workspace" + > + {applyChangesString} + +

+
); }; From 7338acbc7d3ff963cfe061b5a58814fce1996cc8 Mon Sep 17 00:00:00 2001 From: Mat Schaffer Date: Wed, 29 Jun 2022 22:20:03 +0900 Subject: [PATCH 09/10] [Metrics UI] Rename "Metrics" to "Infrastructure" in appropriate places (#135278) Co-authored-by: Carlos Crespo --- x-pack/plugins/infra/public/plugin.ts | 4 ++-- .../feature_controls/infrastructure_security.ts | 8 ++++---- .../feature_controls/infrastructure_spaces.ts | 16 ++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index f591acbde9d92..724b1b1f01d9b 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -98,7 +98,7 @@ export class Plugin implements InfraClientPluginClass { ...(capabilities.infrastructure.show ? [ { - label: 'Metrics', + label: 'Infrastructure', sortKey: 300, entries: [ { label: 'Inventory', app: 'metrics', path: '/inventory' }, @@ -169,7 +169,7 @@ export class Plugin implements InfraClientPluginClass { core.application.register({ id: 'metrics', title: i18n.translate('xpack.infra.metrics.pluginTitle', { - defaultMessage: 'Metrics', + defaultMessage: 'Infrastructure', }), euiIconType: 'logoObservability', order: 8200, diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts index f713c903ebe1e..3c9240ed4ff8d 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts @@ -61,9 +61,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { ]); }); - it('shows metrics navlink', async () => { + it('shows infrastructure navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Alerts', 'Metrics', 'Stack Management']); + expect(navLinks).to.eql(['Overview', 'Alerts', 'Infrastructure', 'Stack Management']); }); describe('infrastructure landing page without data', () => { @@ -161,7 +161,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows metrics navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Alerts', 'Metrics', 'Stack Management']); + expect(navLinks).to.eql(['Overview', 'Alerts', 'Infrastructure', 'Stack Management']); }); describe('infrastructure landing page without data', () => { @@ -359,7 +359,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't show metrics navlink`, async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.not.contain(['Metrics']); + expect(navLinks).to.not.contain(['Infrastructure']); }); it(`metrics app is inaccessible and returns a 403`, async () => { diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts index 545eb08223693..263bf1c9b0d37 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_spaces.ts @@ -39,15 +39,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await spacesService.delete('custom_space'); }); - it('shows Metrics navlink', async () => { + it('shows Infrastructure navlink', async () => { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.contain('Metrics'); + expect(navLinks).to.contain('Infrastructure'); }); - it(`Metrics app is accessible`, async () => { + it(`Infrastructure app is accessible`, async () => { await PageObjects.common.navigateToApp('infraOps', { basePath: '/s/custom_space', }); @@ -72,15 +72,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana'); }); - it(`doesn't show metrics navlink`, async () => { + it(`doesn't show infrastructure navlink`, async () => { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).not.to.contain('Metrics'); + expect(navLinks).not.to.contain('Infrastructure'); }); - it(`metrics app is inaccessible and Application Not Found message is rendered`, async () => { + it(`infrastructure app is inaccessible and Application Not Found message is rendered`, async () => { await PageObjects.common.navigateToActualUrl('infraOps', '', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, @@ -114,7 +114,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana'); }); - it(`Metrics app is accessible`, async () => { + it(`Infrastructure app is accessible`, async () => { await PageObjects.common.navigateToApp('infraOps', { basePath: '/s/custom_space', }); @@ -139,7 +139,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana'); }); - it(`Metrics app is accessible`, async () => { + it(`Infrastructure app is accessible`, async () => { await PageObjects.common.navigateToApp('infraOps', { basePath: '/s/custom_space', }); From 111b6f4b9926fdc8d89886ae214ef429c8e90618 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Wed, 29 Jun 2022 15:29:31 +0200 Subject: [PATCH 10/10] Move server-side executionContext service to packages (#135396) * create the empty server execution-context packages * move src/core/server/execution-context into packages * update READMEs * adapt first server/mocks imports * move ECC type to public package * adapt mock imports * adapt more imports * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 6 + packages/BUILD.bazel | 6 + .../BUILD.bazel | 106 ++++++++++++++++++ .../README.md | 4 + .../jest.config.js | 13 +++ .../package.json | 7 ++ .../src}/execution_context_config.ts | 8 +- .../src}/execution_context_container.test.ts | 2 +- .../src}/execution_context_container.ts | 12 +- .../src}/execution_context_service.test.ts | 1 + .../src}/execution_context_service.ts | 36 ++---- .../src}/index.ts | 6 +- .../tsconfig.json | 17 +++ .../BUILD.bazel | 98 ++++++++++++++++ .../README.md | 4 + .../jest.config.js | 13 +++ .../package.json | 7 ++ .../src}/execution_context_service.mock.ts | 6 +- .../src/index.ts | 9 ++ .../tsconfig.json | 17 +++ .../core-execution-context-server/BUILD.bazel | 97 ++++++++++++++++ .../core-execution-context-server/README.md | 4 + .../jest.config.js | 13 +++ .../package.json | 7 ++ .../src/contracts.ts | 29 +++++ .../src/index.ts | 10 ++ .../src/types.ts | 17 +++ .../tsconfig.json | 17 +++ .../capabilities_service.test.ts | 2 +- .../integration_tests/bundle_routes.test.ts | 2 +- .../elasticsearch_service.test.ts | 2 +- .../elasticsearch/elasticsearch_service.ts | 7 +- src/core/server/http/http_server.ts | 2 +- src/core/server/http/http_service.test.ts | 2 +- src/core/server/http/http_service.ts | 2 +- .../cookie_session_storage.test.ts | 2 +- .../http/integration_tests/lifecycle.test.ts | 2 +- .../lifecycle_handlers.test.ts | 2 +- .../http/integration_tests/preboot.test.ts | 2 +- .../http/integration_tests/request.test.ts | 2 +- .../http/integration_tests/router.test.ts | 2 +- src/core/server/index.ts | 9 +- src/core/server/internal_types.ts | 8 +- .../server_collector.test.ts | 2 +- src/core/server/mocks.ts | 4 +- .../routes/integration_tests/get.test.ts | 2 +- .../routes/integration_tests/resolve.test.ts | 2 +- .../server/saved_objects/routes/test_utils.ts | 2 +- src/core/server/server.ts | 6 +- .../routes/integration_tests/status.test.ts | 2 +- yarn.lock | 34 +++++- 51 files changed, 592 insertions(+), 82 deletions(-) create mode 100644 packages/core/execution-context/core-execution-context-server-internal/BUILD.bazel create mode 100644 packages/core/execution-context/core-execution-context-server-internal/README.md create mode 100644 packages/core/execution-context/core-execution-context-server-internal/jest.config.js create mode 100644 packages/core/execution-context/core-execution-context-server-internal/package.json rename {src/core/server/execution_context => packages/core/execution-context/core-execution-context-server-internal/src}/execution_context_config.ts (74%) rename {src/core/server/execution_context => packages/core/execution-context/core-execution-context-server-internal/src}/execution_context_container.test.ts (98%) rename {src/core/server/execution_context => packages/core/execution-context/core-execution-context-server-internal/src}/execution_context_container.ts (92%) rename {src/core/server/execution_context => packages/core/execution-context/core-execution-context-server-internal/src}/execution_context_service.test.ts (99%) rename {src/core/server/execution_context => packages/core/execution-context/core-execution-context-server-internal/src}/execution_context_service.ts (88%) rename {src/core/server/execution_context => packages/core/execution-context/core-execution-context-server-internal/src}/index.ts (69%) create mode 100644 packages/core/execution-context/core-execution-context-server-internal/tsconfig.json create mode 100644 packages/core/execution-context/core-execution-context-server-mocks/BUILD.bazel create mode 100644 packages/core/execution-context/core-execution-context-server-mocks/README.md create mode 100644 packages/core/execution-context/core-execution-context-server-mocks/jest.config.js create mode 100644 packages/core/execution-context/core-execution-context-server-mocks/package.json rename {src/core/server/execution_context => packages/core/execution-context/core-execution-context-server-mocks/src}/execution_context_service.mock.ts (88%) create mode 100644 packages/core/execution-context/core-execution-context-server-mocks/src/index.ts create mode 100644 packages/core/execution-context/core-execution-context-server-mocks/tsconfig.json create mode 100644 packages/core/execution-context/core-execution-context-server/BUILD.bazel create mode 100644 packages/core/execution-context/core-execution-context-server/README.md create mode 100644 packages/core/execution-context/core-execution-context-server/jest.config.js create mode 100644 packages/core/execution-context/core-execution-context-server/package.json create mode 100644 packages/core/execution-context/core-execution-context-server/src/contracts.ts create mode 100644 packages/core/execution-context/core-execution-context-server/src/index.ts create mode 100644 packages/core/execution-context/core-execution-context-server/src/types.ts create mode 100644 packages/core/execution-context/core-execution-context-server/tsconfig.json diff --git a/package.json b/package.json index 3a04f7a53ab02..b70a6c2d3596f 100644 --- a/package.json +++ b/package.json @@ -170,6 +170,9 @@ "@kbn/core-execution-context-browser-internal": "link:bazel-bin/packages/core/execution-context/core-execution-context-browser-internal", "@kbn/core-execution-context-browser-mocks": "link:bazel-bin/packages/core/execution-context/core-execution-context-browser-mocks", "@kbn/core-execution-context-common": "link:bazel-bin/packages/core/execution-context/core-execution-context-common", + "@kbn/core-execution-context-server": "link:bazel-bin/packages/core/execution-context/core-execution-context-server", + "@kbn/core-execution-context-server-internal": "link:bazel-bin/packages/core/execution-context/core-execution-context-server-internal", + "@kbn/core-execution-context-server-mocks": "link:bazel-bin/packages/core/execution-context/core-execution-context-server-mocks", "@kbn/core-fatal-errors-browser": "link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser", "@kbn/core-fatal-errors-browser-internal": "link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-internal", "@kbn/core-fatal-errors-browser-mocks": "link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-mocks", @@ -709,6 +712,9 @@ "@types/kbn__core-execution-context-browser-internal": "link:bazel-bin/packages/core/execution-context/core-execution-context-browser-internal/npm_module_types", "@types/kbn__core-execution-context-browser-mocks": "link:bazel-bin/packages/core/execution-context/core-execution-context-browser-mocks/npm_module_types", "@types/kbn__core-execution-context-common": "link:bazel-bin/packages/core/execution-context/core-execution-context-common/npm_module_types", + "@types/kbn__core-execution-context-server": "link:bazel-bin/packages/core/execution-context/core-execution-context-server/npm_module_types", + "@types/kbn__core-execution-context-server-internal": "link:bazel-bin/packages/core/execution-context/core-execution-context-server-internal/npm_module_types", + "@types/kbn__core-execution-context-server-mocks": "link:bazel-bin/packages/core/execution-context/core-execution-context-server-mocks/npm_module_types", "@types/kbn__core-fatal-errors-browser": "link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser/npm_module_types", "@types/kbn__core-fatal-errors-browser-internal": "link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-internal/npm_module_types", "@types/kbn__core-fatal-errors-browser-mocks": "link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-mocks/npm_module_types", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index b0d576f5d2e7e..463b9adf64574 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -39,6 +39,9 @@ filegroup( "//packages/core/execution-context/core-execution-context-browser-mocks:build", "//packages/core/execution-context/core-execution-context-browser:build", "//packages/core/execution-context/core-execution-context-common:build", + "//packages/core/execution-context/core-execution-context-server-internal:build", + "//packages/core/execution-context/core-execution-context-server-mocks:build", + "//packages/core/execution-context/core-execution-context-server:build", "//packages/core/fatal-errors/core-fatal-errors-browser-internal:build", "//packages/core/fatal-errors/core-fatal-errors-browser-mocks:build", "//packages/core/fatal-errors/core-fatal-errors-browser:build", @@ -211,6 +214,9 @@ filegroup( "//packages/core/execution-context/core-execution-context-browser-mocks:build_types", "//packages/core/execution-context/core-execution-context-browser:build_types", "//packages/core/execution-context/core-execution-context-common:build_types", + "//packages/core/execution-context/core-execution-context-server-internal:build_types", + "//packages/core/execution-context/core-execution-context-server-mocks:build_types", + "//packages/core/execution-context/core-execution-context-server:build_types", "//packages/core/fatal-errors/core-fatal-errors-browser-internal:build_types", "//packages/core/fatal-errors/core-fatal-errors-browser-mocks:build_types", "//packages/core/fatal-errors/core-fatal-errors-browser:build_types", diff --git a/packages/core/execution-context/core-execution-context-server-internal/BUILD.bazel b/packages/core/execution-context/core-execution-context-server-internal/BUILD.bazel new file mode 100644 index 0000000000000..3a25e581c2865 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-internal/BUILD.bazel @@ -0,0 +1,106 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-execution-context-server-internal" +PKG_REQUIRE_NAME = "@kbn/core-execution-context-server-internal" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + ], + exclude = [ + "**/*.test.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//lodash", + "@npm//rxjs", + "//packages/kbn-config-schema", +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/lodash", + "@npm//rxjs", + "@npm//elastic-apm-node", + "//packages/kbn-config-schema:npm_module_types", + "//packages/kbn-logging:npm_module_types", + "//packages/core/base/core-base-server-internal:npm_module_types", + "//packages/core/execution-context/core-execution-context-common:npm_module_types", + "//packages/core/execution-context/core-execution-context-server:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/execution-context/core-execution-context-server-internal/README.md b/packages/core/execution-context/core-execution-context-server-internal/README.md new file mode 100644 index 0000000000000..409492850893e --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-internal/README.md @@ -0,0 +1,4 @@ +# @kbn/core-execution-context-server-internal + +This package contains the internal types and implementation for Core's server-side execution context service. + diff --git a/packages/core/execution-context/core-execution-context-server-internal/jest.config.js b/packages/core/execution-context/core-execution-context-server-internal/jest.config.js new file mode 100644 index 0000000000000..c2dcbd3abdccc --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-internal/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../..', + roots: ['/packages/core/execution-context/core-execution-context-server-internal'], +}; diff --git a/packages/core/execution-context/core-execution-context-server-internal/package.json b/packages/core/execution-context/core-execution-context-server-internal/package.json new file mode 100644 index 0000000000000..bb5ffa6eed7ea --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-internal/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/core-execution-context-server-internal", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/server/execution_context/execution_context_config.ts b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_config.ts similarity index 74% rename from src/core/server/execution_context/execution_context_config.ts rename to packages/core/execution-context/core-execution-context-server-internal/src/execution_context_config.ts index f62a44a8da4d2..3be4afb7fa812 100644 --- a/src/core/server/execution_context/execution_context_config.ts +++ b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_config.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { TypeOf, schema } from '@kbn/config-schema'; +import { schema } from '@kbn/config-schema'; import type { ServiceConfigDescriptor } from '@kbn/core-base-server-internal'; const configSchema = schema.object({ @@ -16,9 +16,11 @@ const configSchema = schema.object({ /** * @internal */ -export type ExecutionContextConfigType = TypeOf; +export interface ExecutionContextConfigType { + enabled: boolean; +} -export const config: ServiceConfigDescriptor = { +export const executionContextConfig: ServiceConfigDescriptor = { path: 'execution_context', schema: configSchema, }; diff --git a/src/core/server/execution_context/execution_context_container.test.ts b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_container.test.ts similarity index 98% rename from src/core/server/execution_context/execution_context_container.test.ts rename to packages/core/execution-context/core-execution-context-server-internal/src/execution_context_container.test.ts index 0a13519fa1699..2882d208266d4 100644 --- a/src/core/server/execution_context/execution_context_container.test.ts +++ b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_container.test.ts @@ -7,7 +7,7 @@ */ import { Blob } from 'buffer'; -import type { KibanaExecutionContext } from '../../types'; +import type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; import { ExecutionContextContainer, diff --git a/src/core/server/execution_context/execution_context_container.ts b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_container.ts similarity index 92% rename from src/core/server/execution_context/execution_context_container.ts rename to packages/core/execution-context/core-execution-context-server-internal/src/execution_context_container.ts index 1528df6c23140..06f548f9744d0 100644 --- a/src/core/server/execution_context/execution_context_container.ts +++ b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_container.ts @@ -5,7 +5,9 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { KibanaExecutionContext } from '../../types'; + +import type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; +import type { IExecutionContextContainer } from '@kbn/core-execution-context-server'; // Switch to the standard Baggage header. blocked by // https://github.com/elastic/apm-agent-nodejs/issues/2102 @@ -41,14 +43,6 @@ function enforceMaxLength(header: string): string { return header.slice(0, MAX_BAGGAGE_LENGTH); } -/** - * @public - */ -export interface IExecutionContextContainer { - toString(): string; - toJSON(): Readonly; -} - function stringify(ctx: KibanaExecutionContext): string { const encodeURIComponentIfNotEmpty = (val?: string) => encodeURIComponent(val || ''); const stringifiedCtx = `${encodeURIComponentIfNotEmpty(ctx.type)}:${encodeURIComponentIfNotEmpty( diff --git a/src/core/server/execution_context/execution_context_service.test.ts b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_service.test.ts similarity index 99% rename from src/core/server/execution_context/execution_context_service.test.ts rename to packages/core/execution-context/core-execution-context-server-internal/src/execution_context_service.test.ts index 3d3409e514eeb..4ad51d31a0e83 100644 --- a/src/core/server/execution_context/execution_context_service.test.ts +++ b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_service.test.ts @@ -14,6 +14,7 @@ import { } from './execution_context_service'; const delay = (ms: number = 100) => new Promise((resolve) => setTimeout(resolve, ms)); + describe('ExecutionContextService', () => { describe('setup', () => { let service: InternalExecutionContextSetup; diff --git a/src/core/server/execution_context/execution_context_service.ts b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_service.ts similarity index 88% rename from src/core/server/execution_context/execution_context_service.ts rename to packages/core/execution-context/core-execution-context-server-internal/src/execution_context_service.ts index c43690e0dffa0..19c7fa8956baf 100644 --- a/src/core/server/execution_context/execution_context_service.ts +++ b/packages/core/execution-context/core-execution-context-server-internal/src/execution_context_service.ts @@ -6,28 +6,27 @@ * Side Public License, v 1. */ import { AsyncLocalStorage } from 'async_hooks'; -import apm from 'elastic-apm-node'; +import type apm from 'elastic-apm-node'; import { isUndefined, omitBy } from 'lodash'; import type { Subscription } from 'rxjs'; import type { Logger } from '@kbn/logging'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; -import type { KibanaExecutionContext } from '../../types'; +import type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; +import type { IExecutionContextContainer } from '@kbn/core-execution-context-server'; import type { ExecutionContextConfigType } from './execution_context_config'; - -import { - ExecutionContextContainer, - IExecutionContextContainer, - getParentContextFrom, -} from './execution_context_container'; +import { ExecutionContextContainer, getParentContextFrom } from './execution_context_container'; /** * @internal */ export interface IExecutionContext { getParentContextFrom(headers: Record): KibanaExecutionContext | undefined; + setRequestId(requestId: string): void; + set(context: KibanaExecutionContext): void; + /** * The sole purpose of this imperative internal API is to be used by the http service. * The event-based nature of Hapi server doesn't allow us to wrap a request handler with "withContext". @@ -36,11 +35,14 @@ export interface IExecutionContext { * https://nodejs.org/api/async_context.html#async_context_asynclocalstorage_enterwith_store */ get(): IExecutionContextContainer | undefined; + withContext(context: KibanaExecutionContext | undefined, fn: () => R): R; + /** * returns serialized representation to send as a header **/ getAsHeader(): string | undefined; + /** * returns apm labels **/ @@ -57,24 +59,6 @@ export type InternalExecutionContextSetup = IExecutionContext; */ export type InternalExecutionContextStart = IExecutionContext; -/** - * @public - */ -export interface ExecutionContextSetup { - /** - * Keeps track of execution context while the passed function is executed. - * Data are carried over all async operations spawned by the passed function. - * The nested calls stack the registered context on top of each other. - **/ - withContext(context: KibanaExecutionContext | undefined, fn: (...args: any[]) => R): R; - getAsLabels(): apm.Labels; -} - -/** - * @public - */ -export type ExecutionContextStart = ExecutionContextSetup; - export class ExecutionContextService implements CoreService { diff --git a/src/core/server/execution_context/index.ts b/packages/core/execution-context/core-execution-context-server-internal/src/index.ts similarity index 69% rename from src/core/server/execution_context/index.ts rename to packages/core/execution-context/core-execution-context-server-internal/src/index.ts index d34eed5cc34f1..a9a139ac0b4aa 100644 --- a/src/core/server/execution_context/index.ts +++ b/packages/core/execution-context/core-execution-context-server-internal/src/index.ts @@ -6,14 +6,10 @@ * Side Public License, v 1. */ -export type { KibanaExecutionContext } from '../../types'; export { ExecutionContextService } from './execution_context_service'; export type { InternalExecutionContextSetup, InternalExecutionContextStart, - ExecutionContextSetup, - ExecutionContextStart, IExecutionContext, } from './execution_context_service'; -export type { IExecutionContextContainer } from './execution_context_container'; -export { config } from './execution_context_config'; +export { executionContextConfig } from './execution_context_config'; diff --git a/packages/core/execution-context/core-execution-context-server-internal/tsconfig.json b/packages/core/execution-context/core-execution-context-server-internal/tsconfig.json new file mode 100644 index 0000000000000..97a3644c3c703 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-internal/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/execution-context/core-execution-context-server-mocks/BUILD.bazel b/packages/core/execution-context/core-execution-context-server-mocks/BUILD.bazel new file mode 100644 index 0000000000000..07ac3b8a58c9e --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-mocks/BUILD.bazel @@ -0,0 +1,98 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-execution-context-server-mocks" +PKG_REQUIRE_NAME = "@kbn/core-execution-context-server-mocks" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + ], + exclude = [ + "**/*.test.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "//packages/core/execution-context/core-execution-context-common:npm_module_types", + "//packages/core/execution-context/core-execution-context-server:npm_module_types", + "//packages/core/execution-context/core-execution-context-server-internal:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/execution-context/core-execution-context-server-mocks/README.md b/packages/core/execution-context/core-execution-context-server-mocks/README.md new file mode 100644 index 0000000000000..a6dc2547f9133 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-mocks/README.md @@ -0,0 +1,4 @@ +# @kbn/core-execution-context-server-mocks + +This package contains the mocks for Core's server-side execution context service. + diff --git a/packages/core/execution-context/core-execution-context-server-mocks/jest.config.js b/packages/core/execution-context/core-execution-context-server-mocks/jest.config.js new file mode 100644 index 0000000000000..36814720e759a --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-mocks/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../..', + roots: ['/packages/core/execution-context/core-execution-context-server-mocks'], +}; diff --git a/packages/core/execution-context/core-execution-context-server-mocks/package.json b/packages/core/execution-context/core-execution-context-server-mocks/package.json new file mode 100644 index 0000000000000..5434874b3f869 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-mocks/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/core-execution-context-server-mocks", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/server/execution_context/execution_context_service.mock.ts b/packages/core/execution-context/core-execution-context-server-mocks/src/execution_context_service.mock.ts similarity index 88% rename from src/core/server/execution_context/execution_context_service.mock.ts rename to packages/core/execution-context/core-execution-context-server-mocks/src/execution_context_service.mock.ts index 85768eb423f26..4c33105609038 100644 --- a/src/core/server/execution_context/execution_context_service.mock.ts +++ b/packages/core/execution-context/core-execution-context-server-mocks/src/execution_context_service.mock.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import type { KibanaExecutionContext } from '../../types'; +import type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; +import type { ExecutionContextSetup } from '@kbn/core-execution-context-server'; import type { IExecutionContext, InternalExecutionContextSetup, - ExecutionContextSetup, -} from './execution_context_service'; +} from '@kbn/core-execution-context-server-internal'; // attempted removal of any: unsuccessful! In theory, replaceable with /R function withContextMock(context: KibanaExecutionContext | undefined, fn: () => any): any { diff --git a/packages/core/execution-context/core-execution-context-server-mocks/src/index.ts b/packages/core/execution-context/core-execution-context-server-mocks/src/index.ts new file mode 100644 index 0000000000000..8cb6454d141a8 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-mocks/src/index.ts @@ -0,0 +1,9 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { executionContextServiceMock } from './execution_context_service.mock'; diff --git a/packages/core/execution-context/core-execution-context-server-mocks/tsconfig.json b/packages/core/execution-context/core-execution-context-server-mocks/tsconfig.json new file mode 100644 index 0000000000000..97a3644c3c703 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server-mocks/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/execution-context/core-execution-context-server/BUILD.bazel b/packages/core/execution-context/core-execution-context-server/BUILD.bazel new file mode 100644 index 0000000000000..2bcd27b0661e2 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/BUILD.bazel @@ -0,0 +1,97 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-execution-context-server" +PKG_REQUIRE_NAME = "@kbn/core-execution-context-server" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + ], + exclude = [ + "**/*.test.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//elastic-apm-node", + "//packages/core/execution-context/core-execution-context-common:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/execution-context/core-execution-context-server/README.md b/packages/core/execution-context/core-execution-context-server/README.md new file mode 100644 index 0000000000000..017676c5d10c3 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/README.md @@ -0,0 +1,4 @@ +# @kbn/core-execution-context-server + +This package contains the public types for Core's server-side execution context service. + diff --git a/packages/core/execution-context/core-execution-context-server/jest.config.js b/packages/core/execution-context/core-execution-context-server/jest.config.js new file mode 100644 index 0000000000000..39244f8b4ade7 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../..', + roots: ['/packages/core/execution-context/core-execution-context-server'], +}; diff --git a/packages/core/execution-context/core-execution-context-server/package.json b/packages/core/execution-context/core-execution-context-server/package.json new file mode 100644 index 0000000000000..58a8f5adf6eaf --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/core-execution-context-server", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/core/execution-context/core-execution-context-server/src/contracts.ts b/packages/core/execution-context/core-execution-context-server/src/contracts.ts new file mode 100644 index 0000000000000..979eb5f02e7dc --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/src/contracts.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type apm from 'elastic-apm-node'; +import type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; + +/** + * @public + */ +export interface ExecutionContextSetup { + /** + * Keeps track of execution context while the passed function is executed. + * Data are carried over all async operations spawned by the passed function. + * The nested calls stack the registered context on top of each other. + **/ + withContext(context: KibanaExecutionContext | undefined, fn: (...args: any[]) => R): R; + + getAsLabels(): apm.Labels; +} + +/** + * @public + */ +export type ExecutionContextStart = ExecutionContextSetup; diff --git a/packages/core/execution-context/core-execution-context-server/src/index.ts b/packages/core/execution-context/core-execution-context-server/src/index.ts new file mode 100644 index 0000000000000..e7213a5cb9fee --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/src/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { ExecutionContextSetup, ExecutionContextStart } from './contracts'; +export type { IExecutionContextContainer } from './types'; diff --git a/packages/core/execution-context/core-execution-context-server/src/types.ts b/packages/core/execution-context/core-execution-context-server/src/types.ts new file mode 100644 index 0000000000000..e77872062c238 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/src/types.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; + +/** + * @public + */ +export interface IExecutionContextContainer { + toString(): string; + toJSON(): Readonly; +} diff --git a/packages/core/execution-context/core-execution-context-server/tsconfig.json b/packages/core/execution-context/core-execution-context-server/tsconfig.json new file mode 100644 index 0000000000000..97a3644c3c703 --- /dev/null +++ b/packages/core/execution-context/core-execution-context-server/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts index 9f4f229ccae84..f721c3ca76e89 100644 --- a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts +++ b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts @@ -11,9 +11,9 @@ import { REPO_ROOT } from '@kbn/utils'; import { Env } from '@kbn/config'; import { getEnvOptions } from '@kbn/config-mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { HttpService, InternalHttpServicePreboot, InternalHttpServiceSetup } from '../../http'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { CapabilitiesService, CapabilitiesSetup } from '..'; import { createHttpServer } from '../../http/test_utils'; diff --git a/src/core/server/core_app/integration_tests/bundle_routes.test.ts b/src/core/server/core_app/integration_tests/bundle_routes.test.ts index 6da97b4a92463..a01b7479af6d2 100644 --- a/src/core/server/core_app/integration_tests/bundle_routes.test.ts +++ b/src/core/server/core_app/integration_tests/bundle_routes.test.ts @@ -10,8 +10,8 @@ import { resolve } from 'path'; import { readFile } from 'fs/promises'; import supertest from 'supertest'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { HttpService, IRouter } from '../../http'; import { createHttpServer } from '../../http/test_utils'; import { registerRouteForBundle } from '../bundle_routes/bundles_route'; diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.ts b/src/core/server/elasticsearch/elasticsearch_service.test.ts index 254c1c05a243d..61f9cb92fb643 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.test.ts @@ -30,8 +30,8 @@ import { configServiceMock, getEnvOptions } from '@kbn/config-mocks'; import type { CoreContext } from '@kbn/core-base-server-internal'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { analyticsServiceMock } from '@kbn/core-analytics-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { httpServiceMock } from '../http/http_service.mock'; -import { executionContextServiceMock } from '../execution_context/execution_context_service.mock'; import { configSchema, ElasticsearchConfig } from './elasticsearch_config'; import { ElasticsearchService, SetupDeps } from './elasticsearch_service'; import { elasticsearchClientMock } from './client/mocks'; diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index 101ca5cea1bca..17257da73d0fc 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -12,12 +12,15 @@ import { map, shareReplay, takeUntil } from 'rxjs/operators'; import type { Logger } from '@kbn/logging'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { AnalyticsServiceSetup } from '@kbn/core-analytics-server'; -import { registerAnalyticsContextProvider } from './register_analytics_context_provider'; +import type { + InternalExecutionContextSetup, + IExecutionContext, +} from '@kbn/core-execution-context-server-internal'; +import { registerAnalyticsContextProvider } from './register_analytics_context_provider'; import { ClusterClient, ElasticsearchClientConfig } from './client'; import { ElasticsearchConfig, ElasticsearchConfigType } from './elasticsearch_config'; import type { InternalHttpServiceSetup, IAuthHeadersStorage } from '../http'; -import type { InternalExecutionContextSetup, IExecutionContext } from '../execution_context'; import { InternalElasticsearchServicePreboot, InternalElasticsearchServiceSetup, diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index fe714e6c97dea..bf7023fc377db 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -23,8 +23,8 @@ import { firstValueFrom, Observable } from 'rxjs'; import { take } from 'rxjs/operators'; import apm from 'elastic-apm-node'; import type { Logger, LoggerFactory } from '@kbn/logging'; +import type { InternalExecutionContextSetup } from '@kbn/core-execution-context-server-internal'; import { HttpConfig } from './http_config'; -import type { InternalExecutionContextSetup } from '../execution_context'; import { adoptToHapiAuthFormat, AuthenticationHandler } from './lifecycle/auth'; import { adoptToHapiOnPreAuth, OnPreAuthHandler } from './lifecycle/on_pre_auth'; import { adoptToHapiOnPostAuthFormat, OnPostAuthHandler } from './lifecycle/on_post_auth'; diff --git a/src/core/server/http/http_service.test.ts b/src/core/server/http/http_service.test.ts index b3c9194e08e8f..a3c0136f79d8a 100644 --- a/src/core/server/http/http_service.test.ts +++ b/src/core/server/http/http_service.test.ts @@ -14,11 +14,11 @@ import { REPO_ROOT } from '@kbn/utils'; import { ConfigService, Env } from '@kbn/config'; import { getEnvOptions } from '@kbn/config-mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { HttpService } from '.'; import { HttpConfigType, config } from './http_config'; import { httpServerMock } from './http_server.mocks'; import { contextServiceMock } from '../context/context_service.mock'; -import { executionContextServiceMock } from '../execution_context/execution_context_service.mock'; import { config as cspConfig } from '../csp'; import { config as externalUrlConfig, ExternalUrlConfig } from '../external_url'; import { Router } from './router'; diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts index f1ebf775e66bc..41e7087ea8b64 100644 --- a/src/core/server/http/http_service.ts +++ b/src/core/server/http/http_service.ts @@ -14,9 +14,9 @@ import { Logger } from '@kbn/logging'; import { Env } from '@kbn/config'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { PluginOpaqueId } from '@kbn/core-base-common'; +import type { InternalExecutionContextSetup } from '@kbn/core-execution-context-server-internal'; import type { RequestHandlerContext } from '..'; -import type { InternalExecutionContextSetup } from '../execution_context'; import { ContextSetup, InternalContextPreboot } from '../context'; import { CspConfigType, config as cspConfig } from '../csp'; diff --git a/src/core/server/http/integration_tests/cookie_session_storage.test.ts b/src/core/server/http/integration_tests/cookie_session_storage.test.ts index a2969920f490a..7eb522d5de388 100644 --- a/src/core/server/http/integration_tests/cookie_session_storage.test.ts +++ b/src/core/server/http/integration_tests/cookie_session_storage.test.ts @@ -15,12 +15,12 @@ import { ByteSizeValue } from '@kbn/config-schema'; import { Env } from '@kbn/config'; import { getEnvOptions, configServiceMock } from '@kbn/config-mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import type { CoreContext } from '@kbn/core-base-server-internal'; import { HttpService } from '../http_service'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { httpServerMock } from '../http_server.mocks'; import { createCookieSessionStorageFactory } from '../cookie_session_storage'; diff --git a/src/core/server/http/integration_tests/lifecycle.test.ts b/src/core/server/http/integration_tests/lifecycle.test.ts index fc786f219b3d2..15ae184ba5e74 100644 --- a/src/core/server/http/integration_tests/lifecycle.test.ts +++ b/src/core/server/http/integration_tests/lifecycle.test.ts @@ -10,12 +10,12 @@ import supertest from 'supertest'; import { parse as parseCookie } from 'tough-cookie'; import { schema } from '@kbn/config-schema'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { ensureRawRequest } from '../router'; import { HttpService } from '../http_service'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { createHttpServer } from '../test_utils'; let server: HttpService; diff --git a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts index d2bf3a4ed809f..68b2306a6a0bc 100644 --- a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts +++ b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts @@ -18,7 +18,7 @@ import { HttpServerSetup } from '../http_server'; import { IRouter, RouteRegistrar } from '../router'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; // eslint-disable-next-line @typescript-eslint/no-var-requires const pkg = require('../../../../../package.json'); diff --git a/src/core/server/http/integration_tests/preboot.test.ts b/src/core/server/http/integration_tests/preboot.test.ts index bdec218320f6b..d92ca5913f253 100644 --- a/src/core/server/http/integration_tests/preboot.test.ts +++ b/src/core/server/http/integration_tests/preboot.test.ts @@ -9,8 +9,8 @@ import supertest from 'supertest'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { createHttpServer } from '../test_utils'; import { HttpService } from '../http_service'; diff --git a/src/core/server/http/integration_tests/request.test.ts b/src/core/server/http/integration_tests/request.test.ts index 408b4581afc15..3bdf2e38a5447 100644 --- a/src/core/server/http/integration_tests/request.test.ts +++ b/src/core/server/http/integration_tests/request.test.ts @@ -12,11 +12,11 @@ jest.mock('uuid', () => ({ import supertest from 'supertest'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { HttpService } from '../http_service'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { createHttpServer } from '../test_utils'; import { schema } from '@kbn/config-schema'; diff --git a/src/core/server/http/integration_tests/router.test.ts b/src/core/server/http/integration_tests/router.test.ts index f86e8c3599872..de3f45350d90e 100644 --- a/src/core/server/http/integration_tests/router.test.ts +++ b/src/core/server/http/integration_tests/router.test.ts @@ -12,8 +12,8 @@ import supertest from 'supertest'; import { schema } from '@kbn/config-schema'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { createHttpServer } from '../test_utils'; import { HttpService } from '../http_service'; import { Router } from '../router'; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index b2892be79439c..31f706daeccdf 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -38,6 +38,10 @@ import type { AnalyticsServiceStart, AnalyticsServicePreboot, } from '@kbn/core-analytics-server'; +import type { + ExecutionContextSetup, + ExecutionContextStart, +} from '@kbn/core-execution-context-server'; import { ElasticsearchServiceSetup, configSchema as elasticsearchConfigSchema, @@ -89,9 +93,8 @@ export type { ConfigUsageData, }; -import type { ExecutionContextSetup, ExecutionContextStart } from './execution_context'; - -export type { IExecutionContextContainer, KibanaExecutionContext } from './execution_context'; +export type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; +export type { IExecutionContextContainer } from '@kbn/core-execution-context-server'; export { bootstrap } from './bootstrap'; export type { diff --git a/src/core/server/internal_types.ts b/src/core/server/internal_types.ts index 30498d4275077..9be7d8b488af2 100644 --- a/src/core/server/internal_types.ts +++ b/src/core/server/internal_types.ts @@ -17,6 +17,10 @@ import type { AnalyticsServiceStart, } from '@kbn/core-analytics-server'; import type { InternalEnvironmentServiceSetup } from '@kbn/core-environment-server-internal'; +import type { + InternalExecutionContextSetup, + InternalExecutionContextStart, +} from '@kbn/core-execution-context-server-internal'; import { CapabilitiesSetup, CapabilitiesStart } from './capabilities'; import { InternalContextPreboot, ContextSetup } from './context'; import { @@ -45,10 +49,6 @@ import { InternalStatusServiceSetup } from './status'; import { CoreUsageDataStart, InternalCoreUsageDataSetup } from './core_usage_data'; import { I18nServiceSetup } from './i18n'; import { InternalDeprecationsServiceSetup, InternalDeprecationsServiceStart } from './deprecations'; -import type { - InternalExecutionContextSetup, - InternalExecutionContextStart, -} from './execution_context'; import { InternalPrebootServicePreboot } from './preboot'; /** @internal */ diff --git a/src/core/server/metrics/integration_tests/server_collector.test.ts b/src/core/server/metrics/integration_tests/server_collector.test.ts index 92df3c303f37d..0d2751ca3be4f 100644 --- a/src/core/server/metrics/integration_tests/server_collector.test.ts +++ b/src/core/server/metrics/integration_tests/server_collector.test.ts @@ -13,7 +13,7 @@ import { Server as HapiServer } from '@hapi/hapi'; import { createHttpServer } from '../../http/test_utils'; import { HttpService, IRouter } from '../../http'; import { contextServiceMock } from '../../context/context_service.mock'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { ServerMetricsCollector } from '../collectors/server'; import { setTimeout as setTimeoutPromise } from 'timers/promises'; diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 6291a017310e1..bb5fc48e90086 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -16,6 +16,7 @@ import { loggingSystemMock, loggingServiceMock } from '@kbn/core-logging-server- import { analyticsServiceMock } from '@kbn/core-analytics-server-mocks'; import { environmentServiceMock } from '@kbn/core-environment-server-mocks'; import { nodeServiceMock } from '@kbn/core-node-server-mocks'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import type { PluginInitializerContext, CoreSetup, @@ -39,7 +40,6 @@ import { statusServiceMock } from './status/status_service.mock'; import { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock'; import { i18nServiceMock } from './i18n/i18n_service.mock'; import { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; -import { executionContextServiceMock } from './execution_context/execution_context_service.mock'; import { prebootServiceMock } from './preboot/preboot_service.mock'; export { configServiceMock, configDeprecationsMock } from '@kbn/config-mocks'; @@ -63,7 +63,7 @@ export { capabilitiesServiceMock } from './capabilities/capabilities_service.moc export { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock'; export { i18nServiceMock } from './i18n/i18n_service.mock'; export { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; -export { executionContextServiceMock } from './execution_context/execution_context_service.mock'; +export { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; export { docLinksServiceMock } from '@kbn/core-doc-links-server-mocks'; export { analyticsServiceMock } from '@kbn/core-analytics-server-mocks'; diff --git a/src/core/server/saved_objects/routes/integration_tests/get.test.ts b/src/core/server/saved_objects/routes/integration_tests/get.test.ts index 6799925f8e3aa..98d9d9170e5eb 100644 --- a/src/core/server/saved_objects/routes/integration_tests/get.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/get.test.ts @@ -11,7 +11,7 @@ import { registerGetRoute } from '../get'; import { ContextService } from '../../../context'; import { savedObjectsClientMock } from '../../service/saved_objects_client.mock'; import { CoreUsageStatsClient } from '../../../core_usage_data'; -import { executionContextServiceMock } from '../../../execution_context/execution_context_service.mock'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { HttpService, InternalHttpServiceSetup } from '../../../http'; diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts index 82be9ac4c4d96..f551abda188ef 100644 --- a/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts @@ -13,7 +13,7 @@ import { savedObjectsClientMock } from '../../service/saved_objects_client.mock' import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; -import { executionContextServiceMock } from '../../../execution_context/execution_context_service.mock'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { HttpService, InternalHttpServiceSetup } from '../../../http'; import { createHttpServer, createCoreContext } from '../../../http/test_utils'; import { contextServiceMock, coreMock } from '../../../mocks'; diff --git a/src/core/server/saved_objects/routes/test_utils.ts b/src/core/server/saved_objects/routes/test_utils.ts index 616115d9f7d62..0d5e7588ad6ce 100644 --- a/src/core/server/saved_objects/routes/test_utils.ts +++ b/src/core/server/saved_objects/routes/test_utils.ts @@ -6,10 +6,10 @@ * Side Public License, v 1. */ +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { ContextService } from '../../context'; import { createHttpServer, createCoreContext } from '../../http/test_utils'; import { contextServiceMock, coreMock } from '../../mocks'; -import { executionContextServiceMock } from '../../execution_context/execution_context_service.mock'; import { SavedObjectsType } from '../types'; const defaultCoreId = Symbol('core'); diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 7c85967428d43..0c3f482eb9f33 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -25,6 +25,10 @@ import { NodeService, nodeConfig } from '@kbn/core-node-server-internal'; import { AnalyticsService } from '@kbn/core-analytics-server-internal'; import type { AnalyticsServiceSetup } from '@kbn/core-analytics-server'; import { EnvironmentService, pidConfig } from '@kbn/core-environment-server-internal'; +import { + ExecutionContextService, + executionContextConfig, +} from '@kbn/core-execution-context-server-internal'; import { CoreApp } from './core_app'; import { I18nService } from './i18n'; import { ElasticsearchService } from './elasticsearch'; @@ -38,7 +42,6 @@ import { MetricsService, opsConfig } from './metrics'; import { CapabilitiesService } from './capabilities'; // do not try to shorten the import to `./status`, it will break server test mocking import { StatusService } from './status/status_service'; -import { ExecutionContextService } from './execution_context'; import { config as cspConfig } from './csp'; import { config as elasticsearchConfig } from './elasticsearch'; @@ -53,7 +56,6 @@ import { CoreUsageDataService } from './core_usage_data'; import { DeprecationsService, config as deprecationConfig } from './deprecations'; import { CoreRouteHandlerContext } from './core_route_handler_context'; import { config as externalUrlConfig } from './external_url'; -import { config as executionContextConfig } from './execution_context'; import { PrebootCoreRouteHandlerContext } from './preboot_core_route_handler_context'; import { PrebootService } from './preboot'; import { DiscoveredPlugins } from './plugins'; diff --git a/src/core/server/status/routes/integration_tests/status.test.ts b/src/core/server/status/routes/integration_tests/status.test.ts index 3f83a05d0e0a6..0b7599941ae48 100644 --- a/src/core/server/status/routes/integration_tests/status.test.ts +++ b/src/core/server/status/routes/integration_tests/status.test.ts @@ -19,7 +19,7 @@ import { HttpService, InternalHttpServiceSetup } from '../../../http'; import { registerStatusRoute } from '../status'; import { ServiceStatus, ServiceStatusLevels, ServiceStatusLevel } from '../../types'; import { statusServiceMock } from '../../status_service.mock'; -import { executionContextServiceMock } from '../../../execution_context/execution_context_service.mock'; +import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { contextServiceMock } from '../../../context/context_service.mock'; const coreId = Symbol('core'); diff --git a/yarn.lock b/yarn.lock index 096d284b61960..6b2f192159531 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3099,6 +3099,14 @@ version "0.0.0" uid "" +"@kbn/core-environment-server-internal@link:bazel-bin/packages/core/environment/core-environment-server-internal": + version "0.0.0" + uid "" + +"@kbn/core-environment-server-mocks@link:bazel-bin/packages/core/environment/core-environment-server-mocks": + version "0.0.0" + uid "" + "@kbn/core-execution-context-browser-internal@link:bazel-bin/packages/core/execution-context/core-execution-context-browser-internal": version "0.0.0" uid "" @@ -3115,23 +3123,27 @@ version "0.0.0" uid "" -"@kbn/core-fatal-errors-browser-internal@link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-internal": +"@kbn/core-execution-context-server-internal@link:bazel-bin/packages/core/execution-context/core-execution-context-server-internal": version "0.0.0" uid "" -"@kbn/core-fatal-errors-browser-mocks@link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-mocks": +"@kbn/core-execution-context-server-mocks@link:bazel-bin/packages/core/execution-context/core-execution-context-server-mocks": version "0.0.0" uid "" -"@kbn/core-fatal-errors-browser@link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser": +"@kbn/core-execution-context-server@link:bazel-bin/packages/core/execution-context/core-execution-context-server": version "0.0.0" uid "" -"@kbn/core-environment-server-internal@link:bazel-bin/packages/core/environment/core-environment-server-internal": +"@kbn/core-fatal-errors-browser-internal@link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-internal": version "0.0.0" uid "" -"@kbn/core-environment-server-mocks@link:bazel-bin/packages/core/environment/core-environment-server-mocks": +"@kbn/core-fatal-errors-browser-mocks@link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-mocks": + version "0.0.0" + uid "" + +"@kbn/core-fatal-errors-browser@link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser": version "0.0.0" uid "" @@ -6610,6 +6622,18 @@ version "0.0.0" uid "" +"@types/kbn__core-execution-context-server-internal@link:bazel-bin/packages/core/execution-context/core-execution-context-server-internal/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-execution-context-server-mocks@link:bazel-bin/packages/core/execution-context/core-execution-context-server-mocks/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-execution-context-server@link:bazel-bin/packages/core/execution-context/core-execution-context-server/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__core-fatal-errors-browser-internal@link:bazel-bin/packages/core/fatal-errors/core-fatal-errors-browser-internal/npm_module_types": version "0.0.0" uid ""