From 05d2572f6381e0eb9b0c51afa996b9b93222b8b9 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 20 Aug 2021 15:08:08 -0700 Subject: [PATCH 01/93] Fix link to Cloud deployment URL in upgrade step. (#109528) --- .../overview/upgrade_step/upgrade_step.test.tsx | 8 +++++--- .../components/overview/upgrade_step/upgrade_step.tsx | 5 +---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx index 21daed29acaca..bfcd88b91b94a 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx @@ -36,8 +36,8 @@ describe('Overview - Upgrade Step', () => { servicesOverrides: { cloud: { isCloudEnabled: true, - baseUrl: 'https://test.com', - cloudId: '1234', + deploymentUrl: + 'https://cloud.elastic.co./deployments/bfdad4ef99a24212a06d387593686d63', }, }, }); @@ -49,7 +49,9 @@ describe('Overview - Upgrade Step', () => { expect(exists('upgradeSetupCloudLink')).toBe(true); expect(exists('upgradeSetupDocsLink')).toBe(true); - expect(find('upgradeSetupCloudLink').props().href).toBe('https://test.com/deployments/1234'); + expect(find('upgradeSetupCloudLink').props().href).toBe( + 'https://cloud.elastic.co./deployments/bfdad4ef99a24212a06d387593686d63' + ); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx index d66a408cfce77..2ea6777404316 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx @@ -50,10 +50,7 @@ const i18nTexts = { const UpgradeStep = ({ docLinks }: { docLinks: DocLinksStart }) => { const { cloud } = useKibana().services; - const isCloudEnabled: boolean = Boolean(cloud?.isCloudEnabled); - const cloudDeploymentUrl: string = `${cloud?.baseUrl ?? ''}/deployments/${cloud?.cloudId ?? ''}`; - let callToAction; if (isCloudEnabled) { @@ -61,7 +58,7 @@ const UpgradeStep = ({ docLinks }: { docLinks: DocLinksStart }) => { Date: Fri, 20 Aug 2021 18:10:12 -0400 Subject: [PATCH 02/93] [Upgrade Assistant] Refactor CITs --- .../default_deprecation_flyout.test.ts | 6 +- .../es_deprecations/deprecations_list.test.ts | 25 +-- .../es_deprecations/error_handling.test.ts | 3 +- .../es_deprecations.helpers.ts | 150 +++++++++++++++ .../index_settings_deprecation_flyout.test.ts | 14 +- .../ml_snapshots_deprecation_flyout.test.ts | 21 ++- .../reindex_deprecation_flyout.test.ts | 6 +- .../helpers/app_context.mock.ts | 34 ++++ .../helpers/elasticsearch.helpers.ts | 171 ------------------ .../client_integration/helpers/index.ts | 6 +- ...ervices_mock.ts => kibana_context.mock.ts} | 2 +- .../helpers/setup_environment.tsx | 36 +--- .../kibana_deprecations.helpers.ts} | 17 +- .../kibana_deprecations.test.ts} | 3 +- .../fix_deprecation_logs_step.test.tsx | 3 +- .../{helpers => overview}/overview.helpers.ts | 36 +--- .../overview/overview.test.tsx | 3 +- .../review_logs_step.test.tsx | 75 +++----- .../upgrade_step/upgrade_step.test.tsx | 5 +- 19 files changed, 282 insertions(+), 334 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts delete mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/elasticsearch.helpers.ts rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/{services_mock.ts => kibana_context.mock.ts} (96%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/{helpers/kibana.helpers.ts => kibana_deprecations/kibana_deprecations.helpers.ts} (73%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/{kibana.test.ts => kibana_deprecations/kibana_deprecations.test.ts} (98%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/{helpers => overview}/overview.helpers.ts (54%) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts index 917fac8ef666a..1975d0abaf11d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts @@ -7,8 +7,8 @@ import { act } from 'react-dom/test-utils'; -import { ElasticsearchTestBed, setupElasticsearchPage, setupEnvironment } from '../helpers'; - +import { setupEnvironment } from '../helpers'; +import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './mocked_responses'; describe('Default deprecation flyout', () => { @@ -39,7 +39,7 @@ describe('Default deprecation flyout', () => { const multiFieldsDeprecation = esDeprecationsMockResponse.deprecations[2]; const { actions, find, exists } = testBed; - await actions.clickDefaultDeprecationAt(0); + await actions.table.clickDeprecationRowAt('default', 0); expect(exists('defaultDeprecationDetails')).toBe(true); expect(find('defaultDeprecationDetails.flyoutTitle').text()).toContain( diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index ceebc528f0bc4..f040de1c318fd 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -9,7 +9,8 @@ import { act } from 'react-dom/test-utils'; import { API_BASE_PATH } from '../../../common/constants'; import type { MlAction } from '../../../common/types'; -import { ElasticsearchTestBed, setupElasticsearchPage, setupEnvironment } from '../helpers'; +import { setupEnvironment } from '../helpers'; +import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, @@ -56,7 +57,7 @@ describe('Deprecations table', () => { const { actions } = testBed; const totalRequests = server.requests.length; - await actions.clickRefreshButton(); + await actions.table.clickRefreshButton(); const mlDeprecation = esDeprecationsMockResponse.deprecations[0]; const reindexDeprecation = esDeprecationsMockResponse.deprecations[3]; @@ -80,7 +81,7 @@ describe('Deprecations table', () => { it('filters results by "critical" status', async () => { const { find, actions } = testBed; - await actions.clickCriticalFilterButton(); + await actions.searchBar.clickCriticalFilterButton(); const criticalDeprecations = esDeprecationsMockResponse.deprecations.filter( (deprecation) => deprecation.isCritical @@ -88,7 +89,7 @@ describe('Deprecations table', () => { expect(find('deprecationTableRow').length).toEqual(criticalDeprecations.length); - await actions.clickCriticalFilterButton(); + await actions.searchBar.clickCriticalFilterButton(); expect(find('deprecationTableRow').length).toEqual( esDeprecationsMockResponse.deprecations.length @@ -98,7 +99,7 @@ describe('Deprecations table', () => { it('filters results by type', async () => { const { component, find, actions } = testBed; - await actions.clickTypeFilterDropdownAt(0); + await actions.searchBar.clickTypeFilterDropdownAt(0); // We need to read the document "body" as the filter dropdown options are added there and not inside // the component DOM tree. @@ -125,7 +126,7 @@ describe('Deprecations table', () => { const { find, actions } = testBed; const multiFieldsDeprecation = esDeprecationsMockResponse.deprecations[2]; - await actions.setSearchInputValue(multiFieldsDeprecation.message); + await actions.searchBar.setSearchInputValue(multiFieldsDeprecation.message); expect(find('deprecationTableRow').length).toEqual(1); expect(find('deprecationTableRow').at(0).text()).toContain(multiFieldsDeprecation.message); @@ -134,7 +135,7 @@ describe('Deprecations table', () => { it('shows error for invalid search queries', async () => { const { find, exists, actions } = testBed; - await actions.setSearchInputValue('%'); + await actions.searchBar.setSearchInputValue('%'); expect(exists('invalidSearchQueryMessage')).toBe(true); expect(find('invalidSearchQueryMessage').text()).toContain('Invalid search'); @@ -143,7 +144,7 @@ describe('Deprecations table', () => { it('shows message when search query does not return results', async () => { const { find, actions, exists } = testBed; - await actions.setSearchInputValue('foobarbaz'); + await actions.searchBar.setSearchInputValue('foobarbaz'); expect(exists('noDeprecationsRow')).toBe(true); expect(find('noDeprecationsRow').text()).toContain( @@ -183,7 +184,7 @@ describe('Deprecations table', () => { expect(find('deprecationTableRow').length).toEqual(50); // Navigate to the next page - await actions.clickPaginationAt(1); + await actions.pagination.clickPaginationAt(1); // On the second (last) page, we expect to see the remaining deprecations expect(find('deprecationTableRow').length).toEqual(deprecations.length - 50); @@ -192,7 +193,7 @@ describe('Deprecations table', () => { it('allows the number of viewable rows to change', async () => { const { find, actions, component } = testBed; - await actions.clickRowsPerPageDropdown(); + await actions.pagination.clickRowsPerPageDropdown(); // We need to read the document "body" as the rows-per-page dropdown options are added there and not inside // the component DOM tree. @@ -219,7 +220,7 @@ describe('Deprecations table', () => { const criticalDeprecations = deprecations.filter((deprecation) => deprecation.isCritical); - await actions.clickCriticalFilterButton(); + await actions.searchBar.clickCriticalFilterButton(); // Only 40 critical deprecations, so only one page should show expect(find('esDeprecationsPagination').find('.euiPagination__item').length).toEqual(1); @@ -232,7 +233,7 @@ describe('Deprecations table', () => { (deprecation) => deprecation.correctiveAction?.type === 'reindex' ); - await actions.setSearchInputValue('Index created before 7.0'); + await actions.searchBar.setSearchInputValue('Index created before 7.0'); // Only 20 deprecations that match, so only one page should show expect(find('esDeprecationsPagination').find('.euiPagination__item').length).toEqual(1); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts index 8d3616a1b9d6b..6314b4630f850 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts @@ -7,7 +7,8 @@ import { act } from 'react-dom/test-utils'; -import { ElasticsearchTestBed, setupElasticsearchPage, setupEnvironment } from '../helpers'; +import { setupEnvironment } from '../helpers'; +import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; describe('Error handling', () => { let testBed: ElasticsearchTestBed; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts new file mode 100644 index 0000000000000..96474f66dc629 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts @@ -0,0 +1,150 @@ +/* + * 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 { act } from 'react-dom/test-utils'; + +import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; +import { EsDeprecations } from '../../../public/application/components/es_deprecations'; +import { WithAppDependencies } from '../helpers'; + +const testBedConfig: TestBedConfig = { + memoryRouter: { + initialEntries: ['/es_deprecations'], + componentRoutePath: '/es_deprecations', + }, + doMountAsync: true, +}; + +export type ElasticsearchTestBed = TestBed & { + actions: ReturnType; +}; + +const createActions = (testBed: TestBed) => { + const { component, find } = testBed; + + /** + * User Actions + */ + + const table = { + clickRefreshButton: async () => { + await act(async () => { + find('refreshButton').simulate('click'); + }); + + component.update(); + }, + clickDeprecationRowAt: async ( + deprecationType: 'mlSnapshot' | 'indexSetting' | 'reindex' | 'default', + index: number + ) => { + await act(async () => { + find(`deprecation-${deprecationType}`).at(index).simulate('click'); + }); + + component.update(); + }, + }; + + const searchBar = { + clickTypeFilterDropdownAt: async (index: number) => { + await act(async () => { + // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector + find('searchBarContainer') + .find('.euiPopover') + .find('.euiFilterButton') + .at(index) + .simulate('click'); + }); + + component.update(); + }, + setSearchInputValue: async (searchValue: string) => { + await act(async () => { + find('searchBarContainer') + .find('input') + .simulate('keyup', { target: { value: searchValue } }); + }); + + component.update(); + }, + clickCriticalFilterButton: async () => { + await act(async () => { + // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector + find('searchBarContainer').find('.euiFilterButton').at(0).simulate('click'); + }); + + component.update(); + }, + }; + + const pagination = { + clickPaginationAt: async (index: number) => { + await act(async () => { + find(`pagination-button-${index}`).simulate('click'); + }); + + component.update(); + }, + clickRowsPerPageDropdown: async () => { + await act(async () => { + find('tablePaginationPopoverButton').simulate('click'); + }); + + component.update(); + }, + }; + + const mlDeprecationFlyout = { + clickUpgradeSnapshot: async () => { + await act(async () => { + find('mlSnapshotDetails.upgradeSnapshotButton').simulate('click'); + }); + + component.update(); + }, + clickDeleteSnapshot: async () => { + await act(async () => { + find('mlSnapshotDetails.deleteSnapshotButton').simulate('click'); + }); + + component.update(); + }, + }; + + const indexSettingsDeprecationFlyout = { + clickDeleteSettingsButton: async () => { + await act(async () => { + find('deleteSettingsButton').simulate('click'); + }); + + component.update(); + }, + }; + + return { + table, + searchBar, + pagination, + mlDeprecationFlyout, + indexSettingsDeprecationFlyout, + }; +}; + +export const setupElasticsearchPage = async ( + overrides?: Record +): Promise => { + const initTestBed = registerTestBed( + WithAppDependencies(EsDeprecations, overrides), + testBedConfig + ); + const testBed = await initTestBed(); + + return { + ...testBed, + actions: createActions(testBed), + }; +}; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts index efeb78a507160..e3cefe313063a 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts @@ -7,8 +7,8 @@ import { act } from 'react-dom/test-utils'; -import { ElasticsearchTestBed, setupElasticsearchPage, setupEnvironment } from '../helpers'; - +import { setupEnvironment } from '../helpers'; +import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './mocked_responses'; describe('Index settings deprecation flyout', () => { @@ -37,7 +37,7 @@ describe('Index settings deprecation flyout', () => { component.update(); - await actions.clickIndexSettingsDeprecationAt(0); + await actions.table.clickDeprecationRowAt('indexSetting', 0); expect(exists('indexSettingsDetails')).toBe(true); expect(find('indexSettingsDetails.flyoutTitle').text()).toContain( @@ -53,7 +53,7 @@ describe('Index settings deprecation flyout', () => { acknowledged: true, }); - await actions.clickDeleteSettingsButton(); + await actions.indexSettingsDeprecationFlyout.clickDeleteSettingsButton(); const request = server.requests[server.requests.length - 1]; @@ -69,7 +69,7 @@ describe('Index settings deprecation flyout', () => { ); // Reopen the flyout - await actions.clickIndexSettingsDeprecationAt(0); + await actions.table.clickDeprecationRowAt('indexSetting', 0); // Verify prompt to remove setting no longer displays expect(find('removeSettingsPrompt').length).toEqual(0); @@ -87,7 +87,7 @@ describe('Index settings deprecation flyout', () => { httpRequestsMockHelpers.setUpdateIndexSettingsResponse(undefined, error); - await actions.clickDeleteSettingsButton(); + await actions.indexSettingsDeprecationFlyout.clickDeleteSettingsButton(); const request = server.requests[server.requests.length - 1]; @@ -103,7 +103,7 @@ describe('Index settings deprecation flyout', () => { ); // Reopen the flyout - await actions.clickIndexSettingsDeprecationAt(0); + await actions.table.clickDeprecationRowAt('indexSetting', 0); // Verify the flyout shows an error message expect(find('indexSettingsDetails.deleteSettingsError').text()).toContain( diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts index 909976355cd31..6a97dd24286db 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts @@ -8,7 +8,8 @@ import { act } from 'react-dom/test-utils'; import type { MlAction } from '../../../common/types'; -import { ElasticsearchTestBed, setupElasticsearchPage, setupEnvironment } from '../helpers'; +import { setupEnvironment } from '../helpers'; +import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './mocked_responses'; describe('Machine learning deprecation flyout', () => { @@ -37,7 +38,7 @@ describe('Machine learning deprecation flyout', () => { component.update(); - await actions.clickMlDeprecationAt(0); + await actions.table.clickDeprecationRowAt('mlSnapshot', 0); expect(exists('mlSnapshotDetails')).toBe(true); expect(find('mlSnapshotDetails.flyoutTitle').text()).toContain( @@ -65,7 +66,7 @@ describe('Machine learning deprecation flyout', () => { expect(find('mlSnapshotDetails.upgradeSnapshotButton').text()).toEqual('Upgrade'); - await actions.clickUpgradeMlSnapshot(); + await actions.mlDeprecationFlyout.clickUpgradeSnapshot(); // First, we expect a POST request to upgrade the snapshot const upgradeRequest = server.requests[server.requests.length - 2]; @@ -83,7 +84,7 @@ describe('Machine learning deprecation flyout', () => { expect(find('mlActionResolutionCell').text()).toContain('Upgrade complete'); // Reopen the flyout - await actions.clickMlDeprecationAt(0); + await actions.table.clickDeprecationRowAt('mlSnapshot', 0); // Flyout actions should not be visible if deprecation was resolved expect(exists('mlSnapshotDetails.upgradeSnapshotButton')).toBe(false); @@ -108,7 +109,7 @@ describe('Machine learning deprecation flyout', () => { error, }); - await actions.clickUpgradeMlSnapshot(); + await actions.mlDeprecationFlyout.clickUpgradeSnapshot(); const upgradeRequest = server.requests[server.requests.length - 1]; expect(upgradeRequest.method).toBe('POST'); @@ -118,7 +119,7 @@ describe('Machine learning deprecation flyout', () => { expect(find('mlActionResolutionCell').text()).toContain('Upgrade failed'); // Reopen the flyout - await actions.clickMlDeprecationAt(0); + await actions.table.clickDeprecationRowAt('mlSnapshot', 0); // Verify the flyout shows an error message expect(find('mlSnapshotDetails.resolveSnapshotError').text()).toContain( @@ -139,7 +140,7 @@ describe('Machine learning deprecation flyout', () => { expect(find('mlSnapshotDetails.deleteSnapshotButton').text()).toEqual('Delete'); - await actions.clickDeleteMlSnapshot(); + await actions.mlDeprecationFlyout.clickDeleteSnapshot(); const request = server.requests[server.requests.length - 1]; @@ -154,7 +155,7 @@ describe('Machine learning deprecation flyout', () => { expect(find('mlActionResolutionCell').at(0).text()).toEqual('Deletion complete'); // Reopen the flyout - await actions.clickMlDeprecationAt(0); + await actions.table.clickDeprecationRowAt('mlSnapshot', 0); }); it('handles delete failure', async () => { @@ -168,7 +169,7 @@ describe('Machine learning deprecation flyout', () => { httpRequestsMockHelpers.setDeleteMlSnapshotResponse(undefined, error); - await actions.clickDeleteMlSnapshot(); + await actions.mlDeprecationFlyout.clickDeleteSnapshot(); const request = server.requests[server.requests.length - 1]; @@ -183,7 +184,7 @@ describe('Machine learning deprecation flyout', () => { expect(find('mlActionResolutionCell').at(0).text()).toEqual('Deletion failed'); // Reopen the flyout - await actions.clickMlDeprecationAt(0); + await actions.table.clickDeprecationRowAt('mlSnapshot', 0); // Verify the flyout shows an error message expect(find('mlSnapshotDetails.resolveSnapshotError').text()).toContain( diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts index c93cdcb1f4d97..d7ca0101d2b74 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts @@ -7,8 +7,8 @@ import { act } from 'react-dom/test-utils'; -import { ElasticsearchTestBed, setupElasticsearchPage, setupEnvironment } from '../helpers'; - +import { setupEnvironment } from '../helpers'; +import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './mocked_responses'; // Note: The reindexing flyout UX is subject to change; more tests should be added here once functionality is built out @@ -40,7 +40,7 @@ describe('Reindex deprecation flyout', () => { const reindexDeprecation = esDeprecationsMockResponse.deprecations[3]; const { actions, find, exists } = testBed; - await actions.clickReindexDeprecationAt(0); + await actions.table.clickDeprecationRowAt('reindex', 0); expect(exists('reindexDetails')).toBe(true); expect(find('reindexDetails.flyoutTitle').text()).toContain( diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts new file mode 100644 index 0000000000000..ce9a1fbf79197 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + deprecationsServiceMock, + docLinksServiceMock, + notificationServiceMock, + applicationServiceMock, +} from 'src/core/public/mocks'; +import { HttpSetup } from 'src/core/public'; + +import { mockKibanaSemverVersion } from '../../../common/constants'; +import { apiService } from '../../../public/application/lib/api'; +import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; + +export const getAppContextMock = (mockHttpClient: HttpSetup) => ({ + http: mockHttpClient, + docLinks: docLinksServiceMock.createStartContract(), + kibanaVersionInfo: { + currentMajor: mockKibanaSemverVersion.major, + prevMajor: mockKibanaSemverVersion.major - 1, + nextMajor: mockKibanaSemverVersion.major + 1, + }, + notifications: notificationServiceMock.createStartContract(), + isReadOnlyMode: false, + api: apiService, + breadcrumbs: breadcrumbService, + getUrlForApp: applicationServiceMock.createStartContract().getUrlForApp, + deprecations: deprecationsServiceMock.createStartContract(), +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/elasticsearch.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/elasticsearch.helpers.ts deleted file mode 100644 index 86737d4925927..0000000000000 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/elasticsearch.helpers.ts +++ /dev/null @@ -1,171 +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 { act } from 'react-dom/test-utils'; - -import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; -import { EsDeprecations } from '../../../public/application/components/es_deprecations'; -import { WithAppDependencies } from './setup_environment'; - -const testBedConfig: TestBedConfig = { - memoryRouter: { - initialEntries: ['/es_deprecations'], - componentRoutePath: '/es_deprecations', - }, - doMountAsync: true, -}; - -export type ElasticsearchTestBed = TestBed & { - actions: ReturnType; -}; - -const createActions = (testBed: TestBed) => { - const { component, find } = testBed; - - /** - * User Actions - */ - const clickRefreshButton = async () => { - await act(async () => { - find('refreshButton').simulate('click'); - }); - - component.update(); - }; - - const clickMlDeprecationAt = async (index: number) => { - await act(async () => { - find('deprecation-mlSnapshot').at(index).simulate('click'); - }); - - component.update(); - }; - - const clickUpgradeMlSnapshot = async () => { - await act(async () => { - find('mlSnapshotDetails.upgradeSnapshotButton').simulate('click'); - }); - - component.update(); - }; - - const clickDeleteMlSnapshot = async () => { - await act(async () => { - find('mlSnapshotDetails.deleteSnapshotButton').simulate('click'); - }); - - component.update(); - }; - - const clickIndexSettingsDeprecationAt = async (index: number) => { - await act(async () => { - find('deprecation-indexSetting').at(index).simulate('click'); - }); - - component.update(); - }; - - const clickDeleteSettingsButton = async () => { - await act(async () => { - find('deleteSettingsButton').simulate('click'); - }); - - component.update(); - }; - - const clickReindexDeprecationAt = async (index: number) => { - await act(async () => { - find('deprecation-reindex').at(index).simulate('click'); - }); - - component.update(); - }; - - const clickDefaultDeprecationAt = async (index: number) => { - await act(async () => { - find('deprecation-default').at(index).simulate('click'); - }); - - component.update(); - }; - - const clickCriticalFilterButton = async () => { - await act(async () => { - // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector - find('searchBarContainer').find('.euiFilterButton').at(0).simulate('click'); - }); - - component.update(); - }; - - const clickTypeFilterDropdownAt = async (index: number) => { - await act(async () => { - // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector - find('searchBarContainer') - .find('.euiPopover') - .find('.euiFilterButton') - .at(index) - .simulate('click'); - }); - - component.update(); - }; - - const setSearchInputValue = async (searchValue: string) => { - await act(async () => { - find('searchBarContainer') - .find('input') - .simulate('keyup', { target: { value: searchValue } }); - }); - - component.update(); - }; - - const clickPaginationAt = async (index: number) => { - await act(async () => { - find(`pagination-button-${index}`).simulate('click'); - }); - - component.update(); - }; - - const clickRowsPerPageDropdown = async () => { - await act(async () => { - find('tablePaginationPopoverButton').simulate('click'); - }); - - component.update(); - }; - - return { - clickRefreshButton, - clickMlDeprecationAt, - clickUpgradeMlSnapshot, - clickDeleteMlSnapshot, - clickIndexSettingsDeprecationAt, - clickDeleteSettingsButton, - clickReindexDeprecationAt, - clickDefaultDeprecationAt, - clickCriticalFilterButton, - clickTypeFilterDropdownAt, - setSearchInputValue, - clickPaginationAt, - clickRowsPerPageDropdown, - }; -}; - -export const setup = async (overrides?: Record): Promise => { - const initTestBed = registerTestBed( - WithAppDependencies(EsDeprecations, overrides), - testBedConfig - ); - const testBed = await initTestBed(); - - return { - ...testBed, - actions: createActions(testBed), - }; -}; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts index b2a1c4e80ec7d..0c30e173ba994 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts @@ -5,8 +5,4 @@ * 2.0. */ -export { setup as setupOverviewPage, OverviewTestBed } from './overview.helpers'; -export { setup as setupElasticsearchPage, ElasticsearchTestBed } from './elasticsearch.helpers'; -export { setup as setupKibanaPage, KibanaTestBed } from './kibana.helpers'; - -export { setupEnvironment, kibanaVersion } from './setup_environment'; +export { setupEnvironment, WithAppDependencies, kibanaVersion } from './setup_environment'; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/services_mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts similarity index 96% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/services_mock.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts index 893b97c5a0ca6..785c8dc49a76c 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/services_mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts @@ -11,7 +11,7 @@ import { applicationServiceMock } from '../../../../../../src/core/public/applic const discoverMock = discoverPluginMock.createStartContract(); -export const servicesMock = { +export const kibanaContextMock = { data: dataPluginMock.createStartContract(), application: applicationServiceMock.createStartContract(), discover: { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx index fbbbc0e07853c..f5b0993a2267f 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx @@ -7,24 +7,20 @@ import React from 'react'; import axios from 'axios'; +import SemVer from 'semver/classes/semver'; // @ts-ignore import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import SemVer from 'semver/classes/semver'; -import { - deprecationsServiceMock, - docLinksServiceMock, - notificationServiceMock, - applicationServiceMock, -} from 'src/core/public/mocks'; + +import { MAJOR_VERSION } from '../../../common/constants'; import { HttpSetup } from 'src/core/public'; import { KibanaContextProvider } from '../../../public/shared_imports'; -import { MAJOR_VERSION } from '../../../common/constants'; import { AppContextProvider } from '../../../public/application/app_context'; import { apiService } from '../../../public/application/lib/api'; import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; import { GlobalFlyout } from '../../../public/shared_imports'; -import { servicesMock } from './services_mock'; +import { kibanaContextMock } from './kibana_context.mock'; +import { getAppContextMock } from './app_context.mock'; import { init as initHttpRequests } from './http_requests'; const { GlobalFlyoutProvider } = GlobalFlyout; @@ -39,27 +35,13 @@ export const WithAppDependencies = apiService.setup(mockHttpClient as unknown as HttpSetup); breadcrumbService.setup(() => ''); - const contextValue = { - http: mockHttpClient as unknown as HttpSetup, - docLinks: docLinksServiceMock.createStartContract(), - kibanaVersionInfo: { - currentMajor: kibanaVersion.major, - prevMajor: kibanaVersion.major - 1, - nextMajor: kibanaVersion.major + 1, - }, - notifications: notificationServiceMock.createStartContract(), - isReadOnlyMode: false, - api: apiService, - breadcrumbs: breadcrumbService, - getUrlForApp: applicationServiceMock.createStartContract().getUrlForApp, - deprecations: deprecationsServiceMock.createStartContract(), - }; + const appContextMock = getAppContextMock(mockHttpClient as unknown as HttpSetup); - const { servicesOverrides, ...contextOverrides } = overrides; + const { kibanaContextOverrides, ...appContextOverrides } = overrides; return ( - - + + diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts similarity index 73% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana.helpers.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts index 370679d7d1a71..860c9249b266a 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts @@ -7,7 +7,7 @@ import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; import { KibanaDeprecationsContent } from '../../../public/application/components/kibana_deprecations'; -import { WithAppDependencies } from './setup_environment'; +import { WithAppDependencies } from '../helpers'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -17,7 +17,7 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -export type KibanaTestBed = TestBed & { +export type KibanaTestBed = TestBed & { actions: ReturnType; }; @@ -36,7 +36,9 @@ const createActions = (testBed: TestBed) => { }; }; -export const setup = async (overrides?: Record): Promise => { +export const setupKibanaPage = async ( + overrides?: Record +): Promise => { const initTestBed = registerTestBed( WithAppDependencies(KibanaDeprecationsContent, overrides), testBedConfig @@ -48,12 +50,3 @@ export const setup = async (overrides?: Record): Promise { let testBed: KibanaTestBed; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.test.tsx index 3db75ba0a342d..67d18a5a2e8f7 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.test.tsx @@ -7,9 +7,10 @@ import { act } from 'react-dom/test-utils'; -import { OverviewTestBed, setupOverviewPage, setupEnvironment } from '../../helpers'; import { DeprecationLoggingStatus } from '../../../../common/types'; import { DEPRECATION_LOGS_SOURCE_ID } from '../../../../common/constants'; +import { setupEnvironment } from '../../helpers'; +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; const getLoggingResponse = (toggle: boolean): DeprecationLoggingStatus => ({ isDeprecationLogIndexingEnabled: toggle, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/overview.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts similarity index 54% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/overview.helpers.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts index 96e12d4806ee3..3ab7f18bbefb8 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/overview.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts @@ -8,7 +8,7 @@ import { act } from 'react-dom/test-utils'; import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; import { Overview } from '../../../public/application/components/overview'; -import { WithAppDependencies } from './setup_environment'; +import { WithAppDependencies } from '../helpers'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -18,7 +18,7 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -export type OverviewTestBed = TestBed & { +export type OverviewTestBed = TestBed & { actions: ReturnType; }; @@ -42,7 +42,9 @@ const createActions = (testBed: TestBed) => { }; }; -export const setup = async (overrides?: Record): Promise => { +export const setupOverviewPage = async ( + overrides?: Record +): Promise => { const initTestBed = registerTestBed(WithAppDependencies(Overview, overrides), testBedConfig); const testBed = await initTestBed(); @@ -51,31 +53,3 @@ export const setup = async (overrides?: Record): Promise { let testBed: OverviewTestBed; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/review_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/review_logs_step.test.tsx index 2afffe989ed1b..b8646540171e5 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/review_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/review_logs_step.test.tsx @@ -9,7 +9,8 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; import * as mockedResponses from './mocked_responses'; -import { OverviewTestBed, setupOverviewPage, setupEnvironment } from '../../helpers'; +import { setupEnvironment } from '../../helpers'; +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; describe('Overview - Fix deprecated settings step', () => { let testBed: OverviewTestBed; @@ -46,27 +47,7 @@ describe('Overview - Fix deprecated settings step', () => { expect(find('esStatsPanel.criticalDeprecations').text()).toContain('1'); }); - test('Handles network failure', async () => { - const error = { - statusCode: 500, - error: 'Cant retrieve deprecations error', - message: 'Cant retrieve deprecations error', - }; - - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - - await act(async () => { - testBed = await setupOverviewPage(); - }); - - const { component, exists } = testBed; - - component.update(); - - expect(exists('esRequestErrorIconTip')).toBe(true); - }); - - test('Hides deprecation counts if it doesnt have any', async () => { + test(`Hides deprecation counts if it doesn't have any`, async () => { httpRequestsMockHelpers.setLoadEsDeprecationsResponse(mockedResponses.esDeprecationsEmpty); await act(async () => { @@ -78,7 +59,7 @@ describe('Overview - Fix deprecated settings step', () => { expect(exists('noDeprecationsLabel')).toBe(true); }); - test('Stats panel navigates to deprecations list if clicked', () => { + test('Stats panel contains link to ES deprecations page', () => { const { component, exists, find } = testBed; component.update(); @@ -87,7 +68,7 @@ describe('Overview - Fix deprecated settings step', () => { expect(find('esStatsPanel').find('a').props().href).toBe('/es_deprecations'); }); - describe('Renders ES errors', () => { + describe('Renders errors', () => { test('handles network failure', async () => { const error = { statusCode: 500, @@ -177,7 +158,7 @@ describe('Overview - Fix deprecated settings step', () => { }); describe('Kibana deprecations', () => { - test('Show deprecation warning and critical counts', () => { + test('Shows deprecation warning and critical counts', () => { const { exists, find } = testBed; expect(exists('kibanaStatsPanel')).toBe(true); @@ -185,26 +166,7 @@ describe('Overview - Fix deprecated settings step', () => { expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain('1'); }); - test('Handles network failure', async () => { - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockRejectedValue(new Error('Internal Server Error')); - - testBed = await setupOverviewPage({ - deprecations: deprecationService, - }); - }); - - const { component, exists } = testBed; - - component.update(); - - expect(exists('kibanaRequestErrorIconTip')).toBe(true); - }); - - test('Hides deprecation count if it doesnt have any', async () => { + test(`Hides deprecation count if it doesn't have any`, async () => { await act(async () => { const deprecationService = deprecationsServiceMock.createStartContract(); deprecationService.getAllDeprecations = jest.fn().mockRejectedValue([]); @@ -221,7 +183,7 @@ describe('Overview - Fix deprecated settings step', () => { expect(exists('kibanaStatsPanel.criticalDeprecations')).toBe(false); }); - test('Stats panel navigates to deprecations list if clicked', () => { + test('Stats panel contains link to Kibana deprecations page', () => { const { component, exists, find } = testBed; component.update(); @@ -229,5 +191,26 @@ describe('Overview - Fix deprecated settings step', () => { expect(exists('kibanaStatsPanel')).toBe(true); expect(find('kibanaStatsPanel').find('a').props().href).toBe('/kibana_deprecations'); }); + + describe('Renders errors', () => { + test('Handles network failure', async () => { + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + deprecationService.getAllDeprecations = jest + .fn() + .mockRejectedValue(new Error('Internal Server Error')); + + testBed = await setupOverviewPage({ + deprecations: deprecationService, + }); + }); + + const { component, exists } = testBed; + + component.update(); + + expect(exists('kibanaRequestErrorIconTip')).toBe(true); + }); + }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx index bfcd88b91b94a..617aea19a129d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx @@ -7,7 +7,8 @@ import { act } from 'react-dom/test-utils'; -import { OverviewTestBed, setupOverviewPage, setupEnvironment } from '../../helpers'; +import { setupEnvironment } from '../../helpers'; +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; describe('Overview - Upgrade Step', () => { let testBed: OverviewTestBed; @@ -33,7 +34,7 @@ describe('Overview - Upgrade Step', () => { test('Shows upgrade cta and link to docs for cloud installations', async () => { await act(async () => { testBed = await setupOverviewPage({ - servicesOverrides: { + kibanaContextOverrides: { cloud: { isCloudEnabled: true, deploymentUrl: From 3c1a3602316eee445953e9746eaca2da6e0f9c55 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 20 Aug 2021 18:37:45 -0700 Subject: [PATCH 03/93] Rename UA steps to fix_issues_step and fix_logs_step. (#109526) * Rename tests accordingly. --- .../fix_issues_step.test.tsx} | 2 +- .../mocked_responses.ts | 0 .../fix_logs_step.test.tsx} | 0 .../public/application/components/overview/_index.scss | 4 ++-- .../{review_logs_step => fix_issues_step}/_index.scss | 0 .../_stats_panel.scss | 0 .../es_stats/es_stats.tsx | 0 .../es_stats/es_stats_error.tsx | 0 .../es_stats/index.ts | 0 .../fix_issues_step.tsx} | 6 +++--- .../{review_logs_step => fix_issues_step}/index.ts | 2 +- .../kibana_stats/index.ts | 0 .../kibana_stats/kibana_stats.tsx | 0 .../no_deprecations/_no_deprecations.scss | 0 .../no_deprecations/index.ts | 0 .../no_deprecations/no_deprecations.tsx | 0 .../_index.scss | 0 .../_deprecation_logging_toggle.scss | 0 .../deprecation_logging_toggle.tsx | 0 .../deprecation_logging_toggle/index.ts | 0 .../external_links.tsx | 0 .../fix_logs_step.tsx} | 6 +++--- .../{fix_deprecation_logs_step => fix_logs_step}/index.ts | 2 +- .../use_deprecation_logging.ts | 0 .../public/application/components/overview/overview.tsx | 8 ++++---- 25 files changed, 15 insertions(+), 15 deletions(-) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/{review_logs_step/review_logs_step.test.tsx => fix_issues_step/fix_issues_step.test.tsx} (99%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/{review_logs_step => fix_issues_step}/mocked_responses.ts (100%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/{fix_deprecation_logs_step/fix_deprecation_logs_step.test.tsx => fix_logs_step/fix_logs_step.test.tsx} (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/_index.scss (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/_stats_panel.scss (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/es_stats/es_stats.tsx (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/es_stats/es_stats_error.tsx (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/es_stats/index.ts (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step/review_logs_step.tsx => fix_issues_step/fix_issues_step.tsx} (88%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/index.ts (81%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/kibana_stats/index.ts (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/kibana_stats/kibana_stats.tsx (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/no_deprecations/_no_deprecations.scss (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/no_deprecations/index.ts (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{review_logs_step => fix_issues_step}/no_deprecations/no_deprecations.tsx (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step => fix_logs_step}/_index.scss (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step => fix_logs_step}/deprecation_logging_toggle/_deprecation_logging_toggle.scss (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step => fix_logs_step}/deprecation_logging_toggle/deprecation_logging_toggle.tsx (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step => fix_logs_step}/deprecation_logging_toggle/index.ts (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step => fix_logs_step}/external_links.tsx (100%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step/fix_deprecation_logs_step.tsx => fix_logs_step/fix_logs_step.tsx} (94%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step => fix_logs_step}/index.ts (77%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/{fix_deprecation_logs_step => fix_logs_step}/use_deprecation_logging.ts (100%) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/review_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx similarity index 99% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/review_logs_step.test.tsx rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx index b8646540171e5..581e80e7c290a 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/review_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx @@ -12,7 +12,7 @@ import * as mockedResponses from './mocked_responses'; import { setupEnvironment } from '../../helpers'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; -describe('Overview - Fix deprecated settings step', () => { +describe('Overview - Fix deprecation issues step', () => { let testBed: OverviewTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/mocked_responses.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts similarity index 100% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/review_logs_step/mocked_responses.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx similarity index 100% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.test.tsx rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss index cbcfbff3bab68..3febfe77b3cf7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss @@ -1,2 +1,2 @@ -@import 'review_logs_step/index'; -@import 'fix_deprecation_logs_step/index'; +@import 'fix_issues_step/index'; +@import 'fix_logs_step/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_index.scss similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/_index.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_index.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/_stats_panel.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_stats_panel.scss similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/_stats_panel.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_stats_panel.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/es_stats/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/es_stats/es_stats.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/es_stats/es_stats_error.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats_error.tsx similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/es_stats/es_stats_error.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats_error.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/es_stats/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/index.ts similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/es_stats/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/index.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/review_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx similarity index 88% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/review_logs_step.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx index 4ebde8b5f847a..12f26a1ea3430 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/review_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx @@ -15,12 +15,12 @@ import { ESDeprecationStats } from './es_stats'; import { KibanaDeprecationStats } from './kibana_stats'; const i18nTexts = { - reviewStepTitle: i18n.translate('xpack.upgradeAssistant.overview.reviewStepTitle', { + reviewStepTitle: i18n.translate('xpack.upgradeAssistant.overview.fixIssuesStepTitle', { defaultMessage: 'Review deprecated settings and resolve issues', }), }; -export const getReviewLogsStep = ({ nextMajor }: { nextMajor: number }): EuiStepProps => { +export const getFixIssuesStep = ({ nextMajor }: { nextMajor: number }): EuiStepProps => { return { title: i18nTexts.reviewStepTitle, status: 'incomplete', @@ -29,7 +29,7 @@ export const getReviewLogsStep = ({ nextMajor }: { nextMajor: number }): EuiStep

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/index.ts similarity index 81% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/index.ts index 231b8ba2d7774..dde6996edfc74 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { getReviewLogsStep } from './review_logs_step'; +export { getFixIssuesStep } from './fix_issues_step'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/kibana_stats/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/index.ts similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/kibana_stats/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/index.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/kibana_stats/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/kibana_stats/kibana_stats.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/no_deprecations/_no_deprecations.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/_no_deprecations.scss similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/no_deprecations/_no_deprecations.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/_no_deprecations.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/no_deprecations/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/index.ts similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/no_deprecations/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/index.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/no_deprecations/no_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/review_logs_step/no_deprecations/no_deprecations.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/_index.scss similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/_index.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/_index.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/deprecation_logging_toggle/_deprecation_logging_toggle.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/_deprecation_logging_toggle.scss similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/deprecation_logging_toggle/_deprecation_logging_toggle.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/_deprecation_logging_toggle.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/deprecation_logging_toggle/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/index.ts similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/deprecation_logging_toggle/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/index.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/external_links.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx similarity index 94% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index a2f1feae4979d..9c22a07ed771b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/fix_deprecation_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -40,7 +40,7 @@ const i18nTexts = { ), }; -const DeprecationLogsPreview: FunctionComponent = () => { +const FixLogsStep: FunctionComponent = () => { const state = useDeprecationLogging(); return ( @@ -81,10 +81,10 @@ const DeprecationLogsPreview: FunctionComponent = () => { ); }; -export const getFixDeprecationLogsStep = (): EuiStepProps => { +export const getFixLogsStep = (): EuiStepProps => { return { title: i18nTexts.identifyStepTitle, status: 'incomplete', - children: , + children: , }; }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/index.ts similarity index 77% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/index.ts index d4794623d8a99..8a9a9faa6d098 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { getFixDeprecationLogsStep } from './fix_deprecation_logs_step'; +export { getFixLogsStep } from './fix_logs_step'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/use_deprecation_logging.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/use_deprecation_logging.ts similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_deprecation_logs_step/use_deprecation_logging.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/use_deprecation_logging.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index f900416873b83..3f6bf25e9abf0 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -21,8 +21,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { useAppContext } from '../../app_context'; -import { getReviewLogsStep } from './review_logs_step'; -import { getFixDeprecationLogsStep } from './fix_deprecation_logs_step'; +import { getFixIssuesStep } from './fix_issues_step'; +import { getFixLogsStep } from './fix_logs_step'; import { getUpgradeStep } from './upgrade_step'; export const Overview: FunctionComponent = () => { @@ -83,8 +83,8 @@ export const Overview: FunctionComponent = () => { From 63349281ebe2e78cba25e341a2da2ad7d9faf7ea Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Mon, 23 Aug 2021 09:25:40 -0400 Subject: [PATCH 04/93] [Upgrade Assistant] Cleanup scss (#109524) --- .../public/application/_index.scss | 1 - .../public/application/components/_index.scss | 2 -- .../components/es_deprecations/_index.scss | 1 - .../deprecation_types/_index.scss | 1 - .../deprecation_types/reindex/_index.scss | 1 - .../reindex/flyout/_index.scss | 1 - .../reindex/flyout/step_progress.tsx | 2 ++ .../components/overview/_index.scss | 2 -- ...stats_panel.scss => _fix_issues_step.scss} | 0 .../overview/fix_issues_step/_index.scss | 2 -- .../fix_issues_step/fix_issues_step.tsx | 2 ++ .../no_deprecations/_no_deprecations.scss | 3 --- .../no_deprecations/no_deprecations.tsx | 25 +++++++++++-------- .../overview/fix_logs_step/_index.scss | 1 - .../deprecation_logging_toggle.tsx | 2 ++ .../upgrade_assistant/public/index.scss | 1 - .../plugins/upgrade_assistant/public/index.ts | 1 - 17 files changed, 20 insertions(+), 28 deletions(-) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss rename x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/{_stats_panel.scss => _fix_issues_step.scss} (100%) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/_no_deprecations.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/_index.scss delete mode 100644 x-pack/plugins/upgrade_assistant/public/index.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/_index.scss deleted file mode 100644 index 841415620d691..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'components/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/_index.scss deleted file mode 100644 index 8f900ca8dc055..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'es_deprecations/index'; -@import 'overview/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/_index.scss deleted file mode 100644 index 4865e977f5261..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'deprecation_types/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/_index.scss deleted file mode 100644 index c3e842941a250..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'reindex/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/_index.scss deleted file mode 100644 index 4cd55614ab4e6..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'flyout/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_index.scss deleted file mode 100644 index 1c9fd599b13a8..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'step_progress'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx index 0973f721a5372..d5947426aee3d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx @@ -10,6 +10,8 @@ import React, { Fragment, ReactNode } from 'react'; import { EuiIcon, EuiLoadingSpinner } from '@elastic/eui'; +import './_step_progress.scss'; + type STATUS = 'incomplete' | 'inProgress' | 'complete' | 'failed' | 'paused' | 'cancelled'; const StepStatus: React.FunctionComponent<{ status: STATUS; idx: number }> = ({ status, idx }) => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss deleted file mode 100644 index 3febfe77b3cf7..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'fix_issues_step/index'; -@import 'fix_logs_step/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_stats_panel.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_fix_issues_step.scss similarity index 100% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_stats_panel.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_fix_issues_step.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_index.scss deleted file mode 100644 index 7eea518d5698e..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'stats_panel'; -@import 'no_deprecations/no_deprecations'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx index 12f26a1ea3430..f235075350e66 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx @@ -14,6 +14,8 @@ import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import { ESDeprecationStats } from './es_stats'; import { KibanaDeprecationStats } from './kibana_stats'; +import './_fix_issues_step.scss'; + const i18nTexts = { reviewStepTitle: i18n.translate('xpack.upgradeAssistant.overview.fixIssuesStepTitle', { defaultMessage: 'Review deprecated settings and resolve issues', diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/_no_deprecations.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/_no_deprecations.scss deleted file mode 100644 index 0697efbd6ee37..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/_no_deprecations.scss +++ /dev/null @@ -1,3 +0,0 @@ -.upgRenderSuccessMessage { - margin-top: $euiSizeL; -} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx index 06fea677aa0a5..2f034d461a24f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx @@ -7,7 +7,7 @@ import React, { FunctionComponent } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; const i18nTexts = { @@ -21,15 +21,18 @@ const i18nTexts = { export const NoDeprecations: FunctionComponent = () => { return ( - - - - - - - {i18nTexts.noDeprecationsText} - - - + <> + + + + + + + + {i18nTexts.noDeprecationsText} + + + + ); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/_index.scss deleted file mode 100644 index 2299c08a4ac31..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'deprecation_logging_toggle/deprecation_logging_toggle'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx index 42b9f073a52f1..6de099fe05ef5 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx @@ -23,6 +23,8 @@ import { i18n } from '@kbn/i18n'; import { ResponseError } from '../../../../lib/api'; import { DeprecationLoggingPreviewProps } from '../../../types'; +import './_deprecation_logging_toggle.scss'; + const i18nTexts = { fetchErrorMessage: i18n.translate( 'xpack.upgradeAssistant.overview.deprecationLogs.fetchErrorMessage', diff --git a/x-pack/plugins/upgrade_assistant/public/index.scss b/x-pack/plugins/upgrade_assistant/public/index.scss deleted file mode 100644 index 9bd47b6473372..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './application/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/index.ts b/x-pack/plugins/upgrade_assistant/public/index.ts index a4091bcb3e1ab..e338b9c044f68 100644 --- a/x-pack/plugins/upgrade_assistant/public/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -import './index.scss'; import { PluginInitializerContext } from 'src/core/public'; import { UpgradeAssistantUIPlugin } from './plugin'; From 2f2dc953a419360680bddb4523382f0c6403d4cf Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Mon, 23 Aug 2021 20:17:59 -0400 Subject: [PATCH 05/93] [Upgrade Assistant] Update readme (#109502) --- docs/developer/plugin-list.asciidoc | 3 +- x-pack/plugins/upgrade_assistant/README.md | 210 ++++++++++++++++----- 2 files changed, 168 insertions(+), 45 deletions(-) diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 3d1fcd51837a3..f2fdd8eb5763b 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -600,8 +600,7 @@ As a developer you can reuse and extend built-in alerts and actions UI functiona |{kib-repo}blob/{branch}/x-pack/plugins/upgrade_assistant/README.md[upgradeAssistant] -|Upgrade Assistant helps users prepare their Stack for being upgraded to the next major. Its primary -purposes are to: +|Upgrade Assistant helps users prepare their Stack for being upgraded to the next major. It will only be enabled on the last minor before the next major release. This is controlled via the config: xpack.upgrade_assistant.readonly (#101296). |{kib-repo}blob/{branch}/x-pack/plugins/uptime/README.md[uptime] diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index a6cb3b431c82b..0c6c2a3f4c772 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -2,66 +2,190 @@ ## About -Upgrade Assistant helps users prepare their Stack for being upgraded to the next major. Its primary -purposes are to: +Upgrade Assistant helps users prepare their Stack for being upgraded to the next major. It will only be enabled on the last minor before the next major release. This is controlled via the config: `xpack.upgrade_assistant.readonly` ([#101296](https://github.com/elastic/kibana/pull/101296)). -* **Surface deprecations.** Deprecations are features that are currently being used that will be -removed in the next major. Surfacing tells the user that there's a problem preventing them -from upgrading. -* **Migrate from deprecation features to supported features.** This addresses the problem, clearing -the path for the upgrade. Generally speaking, once all deprecations are addressed, the user can -safely upgrade. +Its primary purposes are to: + +* **Surface deprecations.** Deprecations are features that are currently being used that will be removed in the next major. Surfacing tells the user that there's a problem preventing them from upgrading. +* **Migrate from deprecated features to supported features.** This addresses the problem, clearing the path for the upgrade. Generally speaking, once all deprecations are addressed, the user can safely upgrade. ### Deprecations -There are two sources of deprecation information: +There are three sources of deprecation information: -* [**Deprecation Info API.**](https://www.elastic.co/guide/en/elasticsearch/reference/master/migration-api-deprecation.html) -This is information about cluster, node, and index level settings that use deprecated features that -will be removed or changed in the next major version. Currently, only cluster and index deprecations -will be surfaced in the Upgrade Assistant. ES server engineers are responsible for adding -deprecations to the Deprecation Info API. -* [**Deprecation logs.**](https://www.elastic.co/guide/en/elasticsearch/reference/current/logging.html#deprecation-logging) +* [**Elasticsearch Deprecation Info API.**](https://www.elastic.co/guide/en/elasticsearch/reference/master/migration-api-deprecation.html) +This is information about Elasticsearch cluster, node, Machine Learning, and index-level settings that use deprecated features that will be removed or changed in the next major version. ES server engineers are responsible for adding deprecations to the Deprecation Info API. +* [**Elasticsearch deprecation logs.**](https://www.elastic.co/guide/en/elasticsearch/reference/current/logging.html#deprecation-logging) These surface runtime deprecations, e.g. a Painless script that uses a deprecated accessor or a request to a deprecated API. These are also generally surfaced as deprecation headers within the response. Even if the cluster state is good, app maintainers need to watch the logs in case -deprecations are discovered as data is migrated. +deprecations are discovered as data is migrated. Starting in 7.x, deprecation logs can be written to a file or a data stream ([#58924](https://github.com/elastic/elasticsearch/pull/58924)). When the data stream exists, the Upgrade Assistant provides a way to analyze the logs through Observability or Discover ([#106521](https://github.com/elastic/kibana/pull/106521)). +* [**Kibana deprecations API.**](https://github.com/elastic/kibana/blob/master/src/core/server/deprecations/README.mdx) This is information about deprecated features and configs in Kibana. These deprecations are only communicated to the user if the deployment is using these features. Kibana engineers are responsible for adding deprecations to the deprecations API for their respective team. ### Fixing problems -Problems can be fixed at various points in the upgrade process. The Upgrade Assistant supports -various upgrade paths and surfaces various types of upgrade-related issues. - -* **Fixing deprecated cluster settings pre-upgrade.** This generally requires fixing some settings -in `elasticsearch.yml`. -* **Migrating indices data pre-upgrade.** This can involve deleting indices so that ES can rebuild -them in the new version, reindexing them so that they're built using a new Lucene version, or -applying a migration script that reindexes them with new settings/mappings/etc. -* **Migrating indices data post-upgrade.** As was the case with APM in the 6.8->7.x upgrade, -sometimes the new data format isn't forwards-compatible. In these cases, the user will perform the -upgrade first and then use the Upgrade Assistant to reindex their data to be compatible with the new -version. - -Deprecations can be handled in a number of ways: - -* **Reindexing.** When a user's index contains deprecations (e.g. mappings) a reindex solves them. -Upgrade Assistant contains migration scripts that are executed as part of the reindex process. -The user will see a "Reindex" button they can click which will apply this script and perform the -reindex. +#### Elasticsearch + +Elasticsearch deprecations can be handled in a number of ways: + +* **Reindexing.** When a user's index contains deprecations (e.g. mappings) a reindex solves them. Currently, the Upgrade Assistant only automates reindexing for old indices. For example, if you are currently on 7.x, and want to migrate to 8.0, but you still have indices that were created on 6.x. For this scenario, the user will see a "Reindex" button that they can click, which will perform the reindex. * Reindexing is an atomic process in Upgrade Assistant, so that ingestion is never disrupted. It works like this: * Create a new index with a "reindexed-" prefix ([#30114](https://github.com/elastic/kibana/pull/30114)). * Create an index alias pointing from the original index name to the prefixed index name. * Reindex from the original index into the prefixed index. * Delete the old index and rename the prefixed index. - * Some apps might require custom scripts, as was the case with APM ([#29845](https://github.com/elastic/kibana/pull/29845)). - In that case the migration performed a reindex with a Painless script (covered by automated tests) - that made the required changes to the data. -* **Update index settings.** Some index settings will need to be updated, which doesn't require a -reindex. An example of this is the "Fix" button that was added for metricbeat and filebeat indices -([#32829](https://github.com/elastic/kibana/pull/32829), [#33439](https://github.com/elastic/kibana/pull/33439)). +* **Updating index settings.** Some index settings will need to be updated, which doesn't require a +reindex. An example of this is the "Remove deprecated settings" button, which is shown when [deprecated translog settings](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html#index-modules-translog-retention) are detected ([#93293](https://github.com/elastic/kibana/pull/93293)). +* **Upgrading or deleting snapshots**. This is specific to Machine Learning. If a user has old Machine Learning job model snapshots, they will need to be upgraded or deleted. The Upgrade Assistant provides a way to resolve this automatically for the user ([#100066](https://github.com/elastic/kibana/pull/100066)). * **Following the docs.** The Deprecation Info API provides links to the deprecation docs. Users will follow these docs to address the problem and make these warnings or errors disappear in the Upgrade Assistant. -* **Stopping/restarting tasks and jobs.** Users had to stop watches and ML jobs and restart them as -soon as reindexing was complete ([#29663](https://github.com/elastic/kibana/pull/29663)). \ No newline at end of file + +#### Kibana + +Kibana deprecations can be handled in one of two ways: + +* **Automatic resolution.** Some deprecations can be fixed automatically through Upgrade Assistant via an API call. When this is possible, users will see a "Quick resolve" button in the Upgrade Assistant. +* **Manual steps.** For deprecations that require the user to address manually, the Upgrade Assistant provides a list of steps to follow as well as a link to documentation. Once the deprecation is addressed, it will no longer appear in the Upgrade Assistant. + +### Steps for testing +#### Elasticsearch deprecations + +To test the Elasticsearch deprecations page ([#107053](https://github.com/elastic/kibana/pull/107053)), you will first need to create a set of deprecations that will be returned from the deprecation info API. + +**1. Reindexing** + + The reindex action appears in UA whenever the deprecation `Index created before XX` is encountered. To reproduce, you will need to start up a cluster on the previous major version (e.g., if you are running 7.x, start a 6.8 cluster). Create a handful of indices, for example: + + ``` + PUT my_index + ``` + + Next, point to the 6.x data directory when running from a 7.x cluster. + + ``` + yarn es snapshot -E path.data=./path_to_6.x_indices +``` + +**2. Upgrading or deleting ML job model snapshots** + + Similar to the reindex action, the ML action requires setting up a cluster on the previous major version. It also requires the trial license to be enabled. Then, you will need to create a few ML jobs in order to trigger snapshots. + + - Add the Kibana sample data. + - Navigate to Machine Learning > Create new job. + - Select `kibana_sample_data_flights` index. + - Select "Single metric job". + - Add an aggregation, field, and job ID. Change the time range to "Absolute" and select a subset of time. + - Click "Create job" + - View the job created and click the "Start datafeed" action associated with it. Select a subset of time and click "Start". You should now have two snapshots created. If you want to add more, repeat the steps above. + + Next, point to the 6.x data directory when running from a 7.x cluster. + + ``` + yarn es snapshot --license trial -E path.data=./path_to_6.x_ml_snapshots + ``` + +**3. Removing deprecated index settings** + + The Upgrade Assistant currently only supports fixing deprecated translog index settings. However [the code](https://github.com/elastic/kibana/blob/master/x-pack/plugins/upgrade_assistant/common/constants.ts#L22) is written in a way to add support for more if necessary. Run the following Console command to trigger the deprecation warning: + + ``` + PUT deprecated_settings + { + "settings": { + "translog.retention.size": "1b", + "translog.retention.age": "5m", + "index.soft_deletes.enabled": true, + } + } + ``` + +**4. Other deprecations with no automatic resolutions** + + Many deprecations emitted from the deprecation info API are too complex to provide an automatic resolution for in UA. In this case, UA provides details about the deprecation as well as a link to documentation. The following requests will emit deprecations from the deprecation info API. This list is *not* exhaustive of all possible deprecations. You can find the full list of [7.x deprecations in the Elasticsearch repo](https://github.com/elastic/elasticsearch/tree/7.x/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation) by grepping `new DeprecationIssue` in the code. + + ``` + PUT /nested_multi_fields + { + "mappings":{ + "properties":{ + "text":{ + "type":"text", + "fields":{ + "english":{ + "type":"text", + "analyzer":"english", + "fields":{ + "english":{ + "type":"text", + "analyzer":"english" + } + } + } + } + } + } + } + } + ``` + + ``` + PUT field_names_enabled + { + "mappings": { + "_field_names": { + "enabled": false + } + } + } + ``` + + ``` + PUT /_cluster/settings + { + "persistent" : { + "indices.lifecycle.poll_interval" : "500ms" + } + } + ``` + + ``` + PUT _template/field_names_enabled + { + "index_patterns": ["foo"], + "mappings": { + "_field_names": { + "enabled": false + } + } + } + ``` + + ``` + // This is only applicable for indices created prior to 7.x + PUT joda_time + { + "mappings" : { + "properties" : { + "datetime": { + "type": "date", + "format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis" + } + } + } + } + ``` + +#### Kibana deprecations +To test the Kibana deprecations page, you will first need to create a set of deprecations that will be returned from the Kibana deprecations API. Refer to the [8.0 Kibana deprecations meta issue](https://github.com/elastic/kibana/issues/109166) for example deprecations and steps to reproduce. + +### Errors + +This is a non-exhaustive list of different error scenarios in Upgrade Assistant. It's recommended to use the [tweak browser extension](https://chrome.google.com/webstore/detail/tweak-mock-api-calls/feahianecghpnipmhphmfgmpdodhcapi?hl=en), or something similar, to mock the API calls. + +- **Error loading deprecation logging status.** Mock a `404` status code to `GET /api/upgrade_assistant/deprecation_logging`. Alternatively, edit [this line](https://github.com/elastic/kibana/blob/545c1420c285af8f5eee56f414bd6eca735aea11/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts#L70) locally and replace `deprecation_logging` with `fake_deprecation_logging`. +- **Error updating deprecation logging status.** Mock a `404` status code to `PUT /api/upgrade_assistant/deprecation_logging`. Alternatively, edit [this line](https://github.com/elastic/kibana/blob/545c1420c285af8f5eee56f414bd6eca735aea11/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts#L77) locally and replace `deprecation_logging` with `fake_deprecation_logging`. +- **Unauthorized error fetching ES deprecations.** Mock a `403` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 403 }` +- **Partially upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": false } }` +- **Upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": true } }` \ No newline at end of file From 296032896e3dfb1801a11c1344242d32f16f366e Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 24 Aug 2021 12:51:41 -0700 Subject: [PATCH 06/93] Add "Back up data" step to UA (#109543) * Add backup step with static content and link to Snapshot and Restore. * Add snapshot_restore locator. * Remove unnecessary describe block from Upgrade Step tests. * Remove unused render_app.tsx. --- cherry.sh | 176 ++++++++++++++++++ .../snapshot_restore/public/locator.ts | 3 +- .../helpers/app_context.mock.ts | 13 ++ .../overview/backup_step/backup_step.test.tsx | 31 +++ .../upgrade_step/upgrade_step.test.tsx | 10 +- x-pack/plugins/upgrade_assistant/kibana.json | 2 +- .../public/application/app_context.tsx | 4 +- .../overview/backup_step/backup_step.tsx | 76 ++++++++ .../components/overview/backup_step/index.ts | 8 + .../components/overview/overview.tsx | 2 + .../overview/upgrade_step/upgrade_step.tsx | 2 +- ...ection.ts => mount_management_section.tsx} | 22 ++- .../public/application/render_app.tsx | 22 --- .../upgrade_assistant/public/plugin.ts | 19 +- .../plugins/upgrade_assistant/public/types.ts | 5 +- 15 files changed, 352 insertions(+), 43 deletions(-) create mode 100644 cherry.sh create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/index.ts rename x-pack/plugins/upgrade_assistant/public/application/{mount_management_section.ts => mount_management_section.tsx} (67%) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/render_app.tsx diff --git a/cherry.sh b/cherry.sh new file mode 100644 index 0000000000000..155bec683225f --- /dev/null +++ b/cherry.sh @@ -0,0 +1,176 @@ +#!/bin/bash + +git cherry-pick ec3c28f29590d2d916826fb066fad059f3eb3152 --strategy-option theirs + + +git cherry-pick af6b908df145576f7249efeb08c9b33bd3805a29 --strategy-option theirs + + +git cherry-pick 03e3baad4d95bdb35269261b55006ecb5e978b8c --strategy-option theirs + + +git cherry-pick 4a14a94942e798b8753639fb82d9cb06cbb0d8f4 --strategy-option theirs + + +git cherry-pick 77fe9ecf306f676f1ff39a52c57a8012e12b0f0a --strategy-option theirs + + +git cherry-pick 7947341c823acb01029a5954a4b55e61a4ed3b43 --strategy-option theirs + + +git cherry-pick 7c79a81b25845304d7bfdd74f5fb3dd77b1aef93 --strategy-option theirs + + +git cherry-pick ec09a417c2ce16b452c3c9ec711553b2112d85c9 --strategy-option theirs + + +git cherry-pick 047fe77093b87ff45c2a6a2fbb3fe4284de8bead --strategy-option theirs + + +git cherry-pick 986ac3b3733ca57ce5cd18f5a66cbcef6e0a91d4 --strategy-option theirs + + +git cherry-pick efdc7d579a4aacffed757ba01593c43aac449740 --strategy-option theirs + + +git cherry-pick f558a7932fe7d7cc7e62f139fdc79fcf17550871 --strategy-option theirs + + +git cherry-pick 0f451a577b268c3f65eda235713bec3978400b91 --strategy-option theirs + + +git cherry-pick f15250e7845afc2a12a26f157ecffc08125c3d31 --strategy-option theirs + + +git cherry-pick ee32afb8490746d290b119440fea85869984c4ba --strategy-option theirs + + +git cherry-pick 1a74022b023f0013d27b186d05db186d1939682a --strategy-option theirs + + +git cherry-pick de660291d421ebbf65308d0fde81e1de8fb16e2d --strategy-option theirs + + +git cherry-pick 25de6438383f86f9cffcd87f5359634cb8048029 --strategy-option theirs + + +git cherry-pick d4dbce0e1e2deb59093cab2baf8eef1d3661f8a3 --strategy-option theirs + + +git cherry-pick 48b25a611ca85f823a9236112ffdaea8118c7f2e --strategy-option theirs + + +git cherry-pick 7779b38aea10ad7983379f60004fae5ce51c5232 --strategy-option theirs + + +git cherry-pick 7515700242278753e2526093a89652edb23ec98e --strategy-option theirs + + +git cherry-pick af9d3f5f42c4c26f4e814ab364941fe994500d5a --strategy-option theirs + + +git cherry-pick 67871d5719b96d1f5cb7242e700b226e3dd4ed3b --strategy-option theirs + + +git cherry-pick 5250db866817873dfc9ca862f3a68e24b3f0fa15 --strategy-option theirs + + +git cherry-pick 426bda8432201bcb55ee83629464b71d8b2614fb --strategy-option theirs + + +git cherry-pick 252889814fc144a34a0f34f6fa726a9b6b75a41e --strategy-option theirs + + +git cherry-pick 5393b374d9ee97107e685eec24c942a422d3ff84 --strategy-option theirs + + +git cherry-pick e23c26fcbd5fd501d6c436097ed3035a98322e33 --strategy-option theirs + + +git cherry-pick 8dd4122285edd2c5981432acd8269382117371ab --strategy-option theirs + + +git cherry-pick c6152461155ddfa6714270099267f28ec147ac1b --strategy-option theirs + + +git cherry-pick ac94ed9aaa3ed62136c79dfa59421389b55c2936 --strategy-option theirs + + +git cherry-pick d7ce247f813763e8ee9fd7faf80c754481a8b260 --strategy-option theirs + + +git cherry-pick 70f2677213b021a968d00f4fda9927dc8a877ff8 --strategy-option theirs + + +git cherry-pick 1ad9a7275759845885ade59b86bec604da8294a4 --strategy-option theirs + + +git cherry-pick 3c35cbf750f28efb088ceb488ffec7c5c7e4e052 --strategy-option theirs + + +git cherry-pick c9292e548cd53c6388b71fdbd64f999337cfb848 --strategy-option theirs + + +git cherry-pick 71bfe79f3be55980737ff3152f197c750073b585 --strategy-option theirs + + +git cherry-pick 52723a5814d66ff073cbc125ea00ac666f34f65b --strategy-option theirs + + +git cherry-pick dacf0c2a6cabf088b0f17f4eca57e01c466286c0 --strategy-option theirs + + +git cherry-pick 991d24bad21ccf4b8350cba2b2ed3ceca6d90cea --strategy-option theirs + + +git cherry-pick b409e2eb50aec6699d9fa61307d1d3b945544782 --strategy-option theirs + + +git cherry-pick 231ab177b8c58c4389056fd205b4df9433cbb4b1 --strategy-option theirs + + +git cherry-pick a85f7a536193834f8d6a3ab0aaf5e3c8ed6d9009 --strategy-option theirs + +git cherry-pick ade05d911c4667e9ec04bc31322e911a13eba391 --strategy-option theirs + + +git cherry-pick 16271f55563db40032e9abb81cc7819965c35232 --strategy-option theirs + + +git cherry-pick c385d498874d4ca34f454e3cb9ad9e4c0e3219ae --strategy-option theirs + + +git cherry-pick 66742934a495ac0095854006169c3c6dada0d68f --strategy-option theirs + + +git cherry-pick 6b3eb50e6ace45eb0310f6ee99e6083425c9a43d --strategy-option theirs + + +git cherry-pick 3042c1115c9f5e3731dc94a95a559e4fb1a6047a --strategy-option theirs + + +git cherry-pick 794366f41590dd609afeea24794db7c029360090 --strategy-option theirs + + +git cherry-pick 0d614dc16593ab3810ff4589019e253c6d38eaf8 --strategy-option theirs + + +git cherry-pick f69faccb9ddd393662fac08ccc3dd284c22feff6 --strategy-option theirs + + +git cherry-pick 2763514508d58e72834bb285a77411c6000dd943 --strategy-option theirs + + +git cherry-pick 7bdfcf1afc29cf35f1d408063d7422bac8166f7a --strategy-option theirs + + +git cherry-pick 1b62981a1a51e4edcaad538fb3c26e3ed1de2b17 --strategy-option theirs + + +git cherry-pick 4732d4a7322433636d8736d53a30cd7ee9b0e4ed --strategy-option theirs + + +git cherry-pick 0e3853a00fce83339058421b807587bcf622e79e --strategy-option theirs + + +git cherry-pick 21d7bc8391169cdf62006c647472823f7d37205f --strategy-option theirs \ No newline at end of file diff --git a/x-pack/plugins/snapshot_restore/public/locator.ts b/x-pack/plugins/snapshot_restore/public/locator.ts index fac7d389d8e96..ba57446a03887 100644 --- a/x-pack/plugins/snapshot_restore/public/locator.ts +++ b/x-pack/plugins/snapshot_restore/public/locator.ts @@ -22,8 +22,7 @@ export interface SnapshotRestoreLocatorDefinitionDependencies { } export class SnapshotRestoreLocatorDefinition - implements LocatorDefinition -{ + implements LocatorDefinition { constructor(protected readonly deps: SnapshotRestoreLocatorDefinitionDependencies) {} public readonly id = SNAPSHOT_RESTORE_LOCATOR_ID; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index ce9a1fbf79197..b8d8e3d2505ef 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -11,12 +11,24 @@ import { notificationServiceMock, applicationServiceMock, } from 'src/core/public/mocks'; +import { sharePluginMock } from 'src/plugins/share/public/mocks'; import { HttpSetup } from 'src/core/public'; import { mockKibanaSemverVersion } from '../../../common/constants'; import { apiService } from '../../../public/application/lib/api'; import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; +// We'll mock these values to avoid testing the locators themselves. +const idToUrlMap = { + SNAPSHOT_RESTORE_LOCATOR: 'snapshotAndRestoreUrl', +}; + +const shareMock = sharePluginMock.createSetupContract(); +shareMock.url.locators.get = (id) => ({ + // @ts-expect-error This object is missing some properties that we're not using in the UI + getUrl: (): string | undefined => idToUrlMap[id], +}); + export const getAppContextMock = (mockHttpClient: HttpSetup) => ({ http: mockHttpClient, docLinks: docLinksServiceMock.createStartContract(), @@ -31,4 +43,5 @@ export const getAppContextMock = (mockHttpClient: HttpSetup) => ({ breadcrumbs: breadcrumbService, getUrlForApp: applicationServiceMock.createStartContract().getUrlForApp, deprecations: deprecationsServiceMock.createStartContract(), + share: shareMock, }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx new file mode 100644 index 0000000000000..ab571790d56c6 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { setupEnvironment } from '../../helpers'; +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; + +describe('Overview - Backup Step', () => { + let testBed: OverviewTestBed; + const { server } = setupEnvironment(); + + beforeEach(async () => { + testBed = await setupOverviewPage(); + testBed.component.update(); + }); + + afterAll(() => { + server.restore(); + }); + + describe('On-prem', () => { + test('Shows link to Snapshot and Restore', () => { + const { exists, find } = testBed; + expect(exists('snapshotRestoreLink')).toBe(true); + expect(find('snapshotRestoreLink').props().href).toBe('snapshotAndRestoreUrl'); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx index 617aea19a129d..61fc6b45fa4c7 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx @@ -23,15 +23,17 @@ describe('Overview - Upgrade Step', () => { server.restore(); }); - describe('Step 3 - Upgrade stack', () => { - test('Shows link to setup upgrade docs for on-prem installations', () => { + describe('On-prem', () => { + test('Shows link to setup upgrade docs', () => { const { exists } = testBed; expect(exists('upgradeSetupDocsLink')).toBe(true); expect(exists('upgradeSetupCloudLink')).toBe(false); }); + }); - test('Shows upgrade cta and link to docs for cloud installations', async () => { + describe('On Cloud', () => { + test('Shows upgrade CTA and link to docs', async () => { await act(async () => { testBed = await setupOverviewPage({ kibanaContextOverrides: { @@ -47,8 +49,8 @@ describe('Overview - Upgrade Step', () => { const { component, exists, find } = testBed; component.update(); - expect(exists('upgradeSetupCloudLink')).toBe(true); expect(exists('upgradeSetupDocsLink')).toBe(true); + expect(exists('upgradeSetupCloudLink')).toBe(true); expect(find('upgradeSetupCloudLink').props().href).toBe( 'https://cloud.elastic.co./deployments/bfdad4ef99a24212a06d387593686d63' diff --git a/x-pack/plugins/upgrade_assistant/kibana.json b/x-pack/plugins/upgrade_assistant/kibana.json index e66f25318a28c..a250ecd55f1a9 100644 --- a/x-pack/plugins/upgrade_assistant/kibana.json +++ b/x-pack/plugins/upgrade_assistant/kibana.json @@ -8,7 +8,7 @@ "githubTeam": "kibana-stack-management" }, "configPath": ["xpack", "upgrade_assistant"], - "requiredPlugins": ["management", "discover", "data", "licensing", "features", "infra"], + "requiredPlugins": ["management", "discover", "data", "licensing", "features", "infra", "share"], "optionalPlugins": ["usageCollection", "cloud"], "requiredBundles": ["esUiShared", "kibanaReact"] } diff --git a/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx index 88b5bd4721c36..9543c1c4db385 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import React, { createContext, useContext } from 'react'; import { CoreStart, DeprecationsServiceStart, @@ -12,7 +13,7 @@ import { HttpSetup, NotificationsStart, } from 'src/core/public'; -import React, { createContext, useContext } from 'react'; +import { SharePluginSetup } from 'src/plugins/share/public'; import { ApiService } from './lib/api'; import { BreadcrumbService } from './lib/breadcrumbs'; @@ -32,6 +33,7 @@ export interface ContextValue { breadcrumbs: BreadcrumbService; getUrlForApp: CoreStart['application']['getUrlForApp']; deprecations: DeprecationsServiceStart; + share: SharePluginSetup; } export const AppContext = createContext({} as any); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx new file mode 100644 index 0000000000000..006d8ed3d38ae --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; +import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; + +import { useAppContext } from '../../../app_context'; + +const i18nTexts = { + backupStepTitle: i18n.translate('xpack.upgradeAssistant.overview.backupStepTitle', { + defaultMessage: 'Back up your data', + }), + + backupStepDescription: i18n.translate('xpack.upgradeAssistant.overview.backupStepDescription', { + defaultMessage: 'Back up your data before addressing any deprecation issues.', + }), +}; + +const SnapshotRestoreAppLink: React.FunctionComponent = () => { + const { share } = useAppContext(); + + const [snapshotRestoreUrl, setSnapshotRestoreUrl] = useState(); + + useEffect(() => { + const getSnapshotRestoreUrl = async () => { + const locator = share.url.locators.get('SNAPSHOT_RESTORE_LOCATOR'); + + if (!locator) { + return; + } + + const url = await locator.getUrl({ + page: 'snapshots', + }); + setSnapshotRestoreUrl(url); + }; + + getSnapshotRestoreUrl(); + }, [share]); + + return ( + + {i18n.translate('xpack.upgradeAssistant.overview.snapshotRestoreLink', { + defaultMessage: 'Create snapshot', + })} + + ); +}; + +const BackupStep: React.FunctionComponent = () => { + return ( + <> + +

{i18nTexts.backupStepDescription}

+
+ + + + + + ); +}; + +export const getBackupStep = (): EuiStepProps => { + return { + title: i18nTexts.backupStepTitle, + status: 'incomplete', + children: , + }; +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/index.ts new file mode 100644 index 0000000000000..8daac9645fa12 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { getBackupStep } from './backup_step'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index 3f6bf25e9abf0..cae6a6e263550 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -21,6 +21,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { useAppContext } from '../../app_context'; +import { getBackupStep } from './backup_step'; import { getFixIssuesStep } from './fix_issues_step'; import { getFixLogsStep } from './fix_logs_step'; import { getUpgradeStep } from './upgrade_step'; @@ -83,6 +84,7 @@ export const Overview: FunctionComponent = () => { { + const { element, ...appDependencies } = deps; + render(, element); + return () => { + unmountComponentAtNode(element); + }; +}; + export async function mountManagementSection( coreSetup: CoreSetup, params: ManagementAppMountParams, kibanaVersionInfo: KibanaVersionContext, readonly: boolean, + share: SharePluginSetup, services: AppServicesContext ) { const [{ i18n, docLinks, notifications, application, deprecations }] = @@ -43,6 +60,7 @@ export async function mountManagementSection( getUrlForApp: application.getUrlForApp, deprecations, application, + share, services, }); } diff --git a/x-pack/plugins/upgrade_assistant/public/application/render_app.tsx b/x-pack/plugins/upgrade_assistant/public/application/render_app.tsx deleted file mode 100644 index 248e6961a74e5..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/render_app.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { AppDependencies, RootComponent } from './app'; - -interface BootDependencies extends AppDependencies { - element: HTMLElement; -} - -export const renderApp = (deps: BootDependencies) => { - const { element, ...appDependencies } = deps; - render(, element); - return () => { - unmountComponentAtNode(element); - }; -}; diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index 32e825fbdc20d..bb6bf35029959 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -21,7 +21,7 @@ export class UpgradeAssistantUIPlugin { constructor(private ctx: PluginInitializerContext) {} - setup(coreSetup: CoreSetup, { management, cloud }: SetupDependencies) { + setup(coreSetup: CoreSetup, { management, cloud, share }: SetupDependencies) { const { readonly, ui: { enabled: isUpgradeAssistantUiEnabled }, @@ -56,14 +56,15 @@ export class UpgradeAssistantUIPlugin docTitle.change(pluginName); - const { mountManagementSection } = await import('./application/mount_management_section'); - const unmountAppCallback = await mountManagementSection( - coreSetup, - params, - kibanaVersionInfo, - readonly, - services - ); + const { mountManagementSection } = await import('./application/mount_management_section'); + const unmountAppCallback = await mountManagementSection( + coreSetup, + params, + kibanaVersionInfo, + readonly, + share, + services + ); return () => { docTitle.reset(); diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index cbeaf22bb095b..b07f0dbc7c206 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -8,19 +8,22 @@ import { DiscoverStart } from 'src/plugins/discover/public'; import { ManagementSetup } from 'src/plugins/management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { SharePluginSetup } from 'src/plugins/share/public'; import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; export interface AppServicesContext { - cloud?: CloudSetup; discover: DiscoverStart; data: DataPublicPluginStart; + cloud?: CloudSetup; } export interface SetupDependencies { management: ManagementSetup; + share: SharePluginSetup; cloud?: CloudSetup; } + export interface StartDependencies { licensing: LicensingPluginStart; discover: DiscoverStart; From 6ee2f92a5e83ec3e2db96856d9355ea226707840 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 24 Aug 2021 17:03:01 -0700 Subject: [PATCH 07/93] Change copy references of 'deprecation issues' to 'deprecation warnings'. (#109963) --- .../es_deprecations/deprecations_list.test.ts | 2 +- .../components/es_deprecations/es_deprecations_table.tsx | 2 +- .../components/overview/backup_step/backup_step.tsx | 2 +- x-pack/plugins/upgrade_assistant/server/routes/status.test.ts | 4 ++-- x-pack/plugins/upgrade_assistant/server/routes/status.ts | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index f040de1c318fd..5a1e32d958164 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -148,7 +148,7 @@ describe('Deprecations table', () => { expect(exists('noDeprecationsRow')).toBe(true); expect(find('noDeprecationsRow').text()).toContain( - 'No Elasticsearch deprecation issues found' + 'No Elasticsearch deprecation warnings found' ); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx index f1654b2030166..956700319b2b4 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx @@ -45,7 +45,7 @@ const i18nTexts = { noDeprecationsMessage: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.table.noDeprecationsMessage', { - defaultMessage: 'No Elasticsearch deprecation issues found', + defaultMessage: 'No Elasticsearch deprecation warnings found', } ), typeFilterLabel: i18n.translate('xpack.upgradeAssistant.esDeprecations.table.typeFilterLabel', { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx index 006d8ed3d38ae..cb5518a66a1ec 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx @@ -18,7 +18,7 @@ const i18nTexts = { }), backupStepDescription: i18n.translate('xpack.upgradeAssistant.overview.backupStepDescription', { - defaultMessage: 'Back up your data before addressing any deprecation issues.', + defaultMessage: 'Back up your data before addressing any deprecation warnings.', }), }; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts index bd5299ad8a4f3..36f8edb1fafee 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts @@ -74,7 +74,7 @@ describe('Status API', () => { expect(resp.payload).toEqual({ readyForUpgrade: false, details: - 'You have 1 Elasticsearch deprecation issues and 1 Kibana deprecation issues that must be resolved before upgrading.', + 'You have 1 Elasticsearch deprecation warnings and 1 Kibana deprecation warnings that must be resolved before upgrading.', }); }); @@ -97,7 +97,7 @@ describe('Status API', () => { expect(resp.status).toEqual(200); expect(resp.payload).toEqual({ readyForUpgrade: true, - details: 'All deprecation issues have been resolved.', + details: 'All deprecation warnings have been resolved.', }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.ts index 1e0a0060de030..c0e917b2c3206 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.ts @@ -45,14 +45,14 @@ export function registerUpgradeStatusRoute({ router }: RouteDependencies) { return i18n.translate( 'xpack.upgradeAssistant.status.allDeprecationsResolvedMessage', { - defaultMessage: 'All deprecation issues have been resolved.', + defaultMessage: 'All deprecation warnings have been resolved.', } ); } return i18n.translate('xpack.upgradeAssistant.status.deprecationsUnresolvedMessage', { defaultMessage: - 'You have {esTotalCriticalDeps} Elasticsearch deprecation issues and {kibanaTotalCriticalDeps} Kibana deprecation issues that must be resolved before upgrading.', + 'You have {esTotalCriticalDeps} Elasticsearch deprecation warnings and {kibanaTotalCriticalDeps} Kibana deprecation warnings that must be resolved before upgrading.', values: { esTotalCriticalDeps, kibanaTotalCriticalDeps }, }); }; From 2aefe8c31b973031103e1c5aeccd6f3530ab64fb Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 25 Aug 2021 19:40:48 -0400 Subject: [PATCH 08/93] [Upgrade Assistant] Address design feedback for ES deprecations page (#109726) --- .../es_deprecations/deprecations_list.test.ts | 14 ++ .../ml_snapshots_deprecation_flyout.test.ts | 14 +- .../public/application/app.tsx | 4 +- .../deprecation_types/ml_snapshots/flyout.tsx | 130 +++++++++++++----- .../ml_snapshots/use_snapshot_state.tsx | 4 +- .../es_deprecations/es_deprecations.tsx | 66 ++++++++- .../es_deprecations_table_cells.tsx | 22 ++- .../public/shared_imports.ts | 2 + 8 files changed, 210 insertions(+), 46 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index 5a1e32d958164..ffee297f6f574 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -77,6 +77,20 @@ describe('Deprecations table', () => { ); }); + it('shows critical and warning deprecations count', () => { + const { find } = testBed; + const criticalDeprecations = esDeprecationsMockResponse.deprecations.filter( + (deprecation) => deprecation.isCritical + ); + const warningDeprecations = esDeprecationsMockResponse.deprecations.filter( + (deprecation) => deprecation.isCritical === false + ); + + expect(find('criticalDeprecationsCount').text()).toContain(criticalDeprecations.length); + + expect(find('warningDeprecationsCount').text()).toContain(warningDeprecations.length); + }); + describe('search bar', () => { it('filters results by "critical" status', async () => { const { find, actions } = testBed; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts index 6a97dd24286db..ff9dae03a2c57 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts @@ -48,7 +48,7 @@ describe('Machine learning deprecation flyout', () => { describe('upgrade snapshots', () => { it('successfully upgrades snapshots', async () => { - const { find, actions, exists } = testBed; + const { find, actions } = testBed; httpRequestsMockHelpers.setUpgradeMlSnapshotResponse({ nodeId: 'my_node', @@ -86,9 +86,10 @@ describe('Machine learning deprecation flyout', () => { // Reopen the flyout await actions.table.clickDeprecationRowAt('mlSnapshot', 0); - // Flyout actions should not be visible if deprecation was resolved - expect(exists('mlSnapshotDetails.upgradeSnapshotButton')).toBe(false); - expect(exists('mlSnapshotDetails.deleteSnapshotButton')).toBe(false); + // Flyout actions should be disabled if deprecation was resolved + expect(find('mlSnapshotDetails.upgradeSnapshotButton').props().disabled).toBe(true); + expect(find('mlSnapshotDetails.upgradeSnapshotButton').text()).toContain('Upgrade complete'); + expect(find('mlSnapshotDetails.deleteSnapshotButton').props().disabled).toBe(true); }); it('handles upgrade failure', async () => { @@ -156,6 +157,11 @@ describe('Machine learning deprecation flyout', () => { // Reopen the flyout await actions.table.clickDeprecationRowAt('mlSnapshot', 0); + + // Flyout actions should be disabled if deprecation was resolved + expect(find('mlSnapshotDetails.deleteSnapshotButton').props().disabled).toBe(true); + expect(find('mlSnapshotDetails.deleteSnapshotButton').text()).toContain('Deletion complete'); + expect(find('mlSnapshotDetails.upgradeSnapshotButton').props().disabled).toBe(true); }); it('handles delete failure', async () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index 864be6e5d996d..8a1ee9a91cabb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -11,7 +11,7 @@ import { I18nStart, ScopedHistory } from 'src/core/public'; import { ApplicationStart } from 'kibana/public'; import { GlobalFlyout } from '../shared_imports'; -import { KibanaContextProvider } from '../shared_imports'; +import { KibanaContextProvider, APP_WRAPPER_CLASS } from '../shared_imports'; import { AppServicesContext } from '../types'; import { AppContextProvider, ContextValue, useAppContext } from './app_context'; import { ComingSoonPrompt } from './components/coming_soon_prompt'; @@ -62,7 +62,7 @@ export const RootComponent = ({ ...contextValue }: AppDependencies) => { return ( - + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index ba72faf2f8c3f..5d61b076119e7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -25,6 +25,7 @@ import { import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { MlSnapshotContext } from './context'; +import { SnapshotState } from './use_snapshot_state'; export interface FixSnapshotsFlyoutProps extends MlSnapshotContext { deprecation: EnrichedDeprecationInfo; @@ -38,12 +39,24 @@ const i18nTexts = { defaultMessage: 'Upgrade', } ), + upgradingButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.upgradingButtonLabel', + { + defaultMessage: 'Upgrading…', + } + ), retryUpgradeButtonLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.retryUpgradeButtonLabel', { defaultMessage: 'Retry upgrade', } ), + upgradeResolvedButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.deleteResolvupgradeResolvedButtonLabeledButtonLabel', + { + defaultMessage: 'Upgrade complete', + } + ), closeButtonLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.closeButtonLabel', { @@ -56,6 +69,18 @@ const i18nTexts = { defaultMessage: 'Delete', } ), + deletingButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.deletingButtonLabel', + { + defaultMessage: 'Deleting…', + } + ), + deleteResolvedButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.deleteResolvedButtonLabel', + { + defaultMessage: 'Deletion complete', + } + ), retryDeleteButtonLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.retryDeleteButtonLabel', { @@ -85,6 +110,44 @@ const i18nTexts = { ), }; +const getDeleteButtonLabel = (snapshotState: SnapshotState) => { + if (snapshotState.action === 'delete') { + if (snapshotState.error) { + return i18nTexts.retryDeleteButtonLabel; + } + + switch (snapshotState.status) { + case 'in_progress': + return i18nTexts.deletingButtonLabel; + case 'complete': + return i18nTexts.deleteResolvedButtonLabel; + case 'idle': + default: + return i18nTexts.deleteButtonLabel; + } + } + return i18nTexts.deleteButtonLabel; +}; + +const getUpgradeButtonLabel = (snapshotState: SnapshotState) => { + if (snapshotState.action === 'upgrade') { + if (snapshotState.error) { + return i18nTexts.retryUpgradeButtonLabel; + } + + switch (snapshotState.status) { + case 'in_progress': + return i18nTexts.upgradingButtonLabel; + case 'complete': + return i18nTexts.upgradeResolvedButtonLabel; + case 'idle': + default: + return i18nTexts.upgradeButtonLabel; + } + } + return i18nTexts.upgradeButtonLabel; +}; + export const FixSnapshotsFlyout = ({ deprecation, closeFlyout, @@ -92,9 +155,6 @@ export const FixSnapshotsFlyout = ({ upgradeSnapshot, deleteSnapshot, }: FixSnapshotsFlyoutProps) => { - // Flag used to hide certain parts of the UI if the deprecation has been resolved or is in progress - const isResolvable = ['idle', 'error'].includes(snapshotState.status); - const onUpgradeSnapshot = () => { upgradeSnapshot(); closeFlyout(); @@ -147,36 +207,40 @@ export const FixSnapshotsFlyout = ({
- {isResolvable && ( - - - - - {snapshotState.action === 'delete' && snapshotState.error - ? i18nTexts.retryDeleteButtonLabel - : i18nTexts.deleteButtonLabel} - - - - - {snapshotState.action === 'upgrade' && snapshotState.error - ? i18nTexts.retryUpgradeButtonLabel - : i18nTexts.upgradeButtonLabel} - - - - - )} + + + + + {getDeleteButtonLabel(snapshotState)} + + + + + {getUpgradeButtonLabel(snapshotState)} + + + +
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx index a724922563e05..39f7c3d37ad52 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx @@ -68,7 +68,7 @@ export const useSnapshotState = ({ return; } - setSnapshotState(data); + setSnapshotState({ ...data, action: 'upgrade' }); // Only keep polling if it exists and is in progress. if (data?.status === 'in_progress') { @@ -97,7 +97,7 @@ export const useSnapshotState = ({ return; } - setSnapshotState(data); + setSnapshotState({ ...data, action: 'upgrade' }); updateSnapshotStatus(); }, [api, jobId, snapshotId, updateSnapshotStatus]); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 38367bd3cfaff..b714ae2ca2fd1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -5,18 +5,44 @@ * 2.0. */ -import React, { useEffect } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { EuiPageHeader, EuiSpacer, EuiPageContent } from '@elastic/eui'; +import { + EuiPageHeader, + EuiSpacer, + EuiPageContent, + EuiFlexGroup, + EuiFlexItem, + EuiHealth, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { EnrichedDeprecationInfo } from '../../../../common/types'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { EsDeprecationsTable } from './es_deprecations_table'; import { EsDeprecationErrors } from './es_deprecation_errors'; import { NoDeprecationsPrompt } from '../shared'; +const getDeprecationCountByLevel = (deprecations: EnrichedDeprecationInfo[]) => { + const criticalDeprecations: EnrichedDeprecationInfo[] = []; + const warningDeprecations: EnrichedDeprecationInfo[] = []; + + deprecations.forEach((deprecation) => { + if (deprecation.isCritical) { + criticalDeprecations.push(deprecation); + return; + } + warningDeprecations.push(deprecation); + }); + + return { + criticalDeprecations: criticalDeprecations.length, + warningDeprecations: warningDeprecations.length, + }; +}; + const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.esDeprecations.pageTitle', { defaultMessage: 'Elasticsearch deprecation warnings', @@ -28,6 +54,20 @@ const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { defaultMessage: 'Loading deprecations…', }), + getCriticalStatusLabel: (count: number) => + i18n.translate('xpack.upgradeAssistant.esDeprecations.criticalStatusLabel', { + defaultMessage: 'Critical: {count}', + values: { + count, + }, + }), + getWarningStatusLabel: (count: number) => + i18n.translate('xpack.upgradeAssistant.esDeprecations.warningStatusLabel', { + defaultMessage: 'Warning: {count}', + values: { + count, + }, + }), }; export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { @@ -41,6 +81,13 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { isInitialRequest, } = api.useLoadEsDeprecations(); + const deprecationsCountByLevel: { + warningDeprecations: number; + criticalDeprecations: number; + } = useMemo(() => getDeprecationCountByLevel(esDeprecations?.deprecations || []), [ + esDeprecations?.deprecations, + ]); + useEffect(() => { breadcrumbs.setBreadcrumbs('esDeprecations'); }, [breadcrumbs]); @@ -82,7 +129,20 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { return (
- + + + + + {i18nTexts.getCriticalStatusLabel(deprecationsCountByLevel.criticalDeprecations)} + + + + + {i18nTexts.getWarningStatusLabel(deprecationsCountByLevel.warningDeprecations)} + + + + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx index dd187f19d5e96..a42ab1baa887f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiBadge, EuiLink } from '@elastic/eui'; +import { EuiBadge, EuiLink, EuiText, EuiToolTip } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../common/types'; import { DEPRECATION_TYPE_MAP } from '../constants'; import { DeprecationTableColumns } from '../types'; @@ -26,6 +26,18 @@ const i18nTexts = { defaultMessage: 'Critical', } ), + manualCellLabel: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.defaultDeprecation.manualCellLabel', + { + defaultMessage: 'Manual', + } + ), + manualCellTooltipLabel: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.reindex.manualCellTooltipLabel', + { + defaultMessage: 'Resolve this deprecation manually.', + } + ), }; export const EsDeprecationsTableCells: React.FunctionComponent = ({ @@ -66,7 +78,13 @@ export const EsDeprecationsTableCells: React.FunctionComponent = ({ return <>{resolutionTableCell}; } - return <>{''}; + return ( + + + {i18nTexts.manualCellLabel} + + + ); } // Default behavior: render value or empty string if undefined diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index 64b52065f63e6..fefa6fd60f806 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -22,4 +22,6 @@ export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/publ export { DataPublicPluginStart } from '../../../../src/plugins/data/public'; +export { APP_WRAPPER_CLASS } from '../../../../src/core/public'; + export const useKibana = () => _useKibana(); From c9aa4fc4ede4934b4927f8a31b2bcd7a3e1edc55 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 26 Aug 2021 16:52:37 +0200 Subject: [PATCH 09/93] [Upgrade Assistant] Add checkpoint feature to Overview page (#109449) --- .../helpers/http_requests.ts | 15 +++ .../fix_logs_step/fix_logs_step.test.tsx | 116 ++++++++++++++++- .../overview/overview.helpers.ts | 22 ++++ .../upgrade_assistant/common/constants.ts | 3 + x-pack/plugins/upgrade_assistant/kibana.json | 2 +- .../deprecations_count_checkpoint.tsx | 121 ++++++++++++++++++ .../deprecations_count_checkpoint/index.ts | 8 ++ .../overview/fix_logs_step/fix_logs_step.tsx | 16 ++- .../public/application/lib/api.ts | 13 +- .../public/shared_imports.ts | 2 + .../upgrade_assistant/server/plugin.ts | 4 +- .../server/routes/__mocks__/request.mock.ts | 1 + .../server/routes/deprecation_logging.test.ts | 69 ++++++++-- .../server/routes/deprecation_logging.ts | 46 +++++++ 14 files changed, 421 insertions(+), 17 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/index.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts index d0c93d74f31f4..924dce1a0be9f 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts @@ -37,6 +37,20 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setLoadDeprecationLogsCountResponse = ( + response?: { count: number }, + error?: ResponseError + ) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + + server.respondWith('GET', `${API_BASE_PATH}/deprecation_logging/count`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + const setUpdateDeprecationLoggingResponse = ( response?: DeprecationLoggingStatus, error?: ResponseError @@ -102,6 +116,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { setUpgradeMlSnapshotResponse, setDeleteMlSnapshotResponse, setUpgradeMlSnapshotStatusResponse, + setLoadDeprecationLogsCountResponse, }; }; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index 67d18a5a2e8f7..c19f06f03ecc2 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -103,14 +103,29 @@ describe('Overview - Fix deprecation logs step', () => { expect(exists('fetchLoggingError')).toBe(true); }); + + test('It doesnt show external links and deprecations count when toggle is disabled', async () => { + httpRequestsMockHelpers.setLoadDeprecationLoggingResponse({ + isDeprecationLogIndexingEnabled: false, + isDeprecationLoggingEnabled: false, + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, component } = testBed; + + component.update(); + + expect(exists('externalLinksTitle')).toBe(false); + expect(exists('deprecationsCountTitle')).toBe(false); + }); }); describe('Step 2 - Analyze logs', () => { beforeEach(async () => { - httpRequestsMockHelpers.setLoadDeprecationLoggingResponse({ - isDeprecationLogIndexingEnabled: true, - isDeprecationLoggingEnabled: true, - }); + httpRequestsMockHelpers.setLoadDeprecationLoggingResponse(getLoggingResponse(true)); }); test('Has a link to see logs in observability app', async () => { @@ -151,4 +166,97 @@ describe('Overview - Fix deprecation logs step', () => { expect(find('viewDiscoverLogs').props().href).toBe('/discover/logs'); }); }); + + describe('Step 3 - Resolve log issues', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadDeprecationLoggingResponse(getLoggingResponse(true)); + }); + + test('With deprecation warnings', async () => { + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 10, + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { find, exists, component } = testBed; + + component.update(); + + expect(exists('hasWarningsCallout')).toBe(true); + expect(find('hasWarningsCallout').text()).toContain('10'); + }); + + test('No deprecation warnings', async () => { + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 0, + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { find, exists, component } = testBed; + + component.update(); + + expect(exists('noWarningsCallout')).toBe(true); + expect(find('noWarningsCallout').text()).toContain('No deprecation warnings'); + }); + + test('Handles errors and can retry', async () => { + const error = { + statusCode: 500, + error: 'Internal server error', + message: 'Internal server error', + }; + + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse(undefined, error); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, actions, component } = testBed; + + component.update(); + + expect(exists('errorCallout')).toBe(true); + + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 0, + }); + + await actions.clickRetryButton(); + + expect(exists('noWarningsCallout')).toBe(true); + }); + + test('Allows user to reset last stored date', async () => { + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 10, + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, actions, component } = testBed; + + component.update(); + + expect(exists('hasWarningsCallout')).toBe(true); + expect(exists('resetLastStoredDate')).toBe(true); + + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 0, + }); + + await actions.clickResetButton(); + + expect(exists('noWarningsCallout')).toBe(true); + }); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts index 3ab7f18bbefb8..1457af010af5b 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts @@ -37,8 +37,30 @@ const createActions = (testBed: TestBed) => { component.update(); }; + const clickRetryButton = async () => { + const { find, component } = testBed; + + await act(async () => { + find('retryButton').simulate('click'); + }); + + component.update(); + }; + + const clickResetButton = async () => { + const { find, component } = testBed; + + await act(async () => { + find('resetLastStoredDate').simulate('click'); + }); + + component.update(); + }; + return { clickDeprecationToggle, + clickRetryButton, + clickResetButton, }; }; diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index 68a6b9e9cdb83..750d5283865c8 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -26,4 +26,7 @@ export const API_BASE_PATH = '/api/upgrade_assistant'; export const DEPRECATION_WARNING_UPPER_LIMIT = 999999; export const DEPRECATION_LOGS_SOURCE_ID = 'deprecation_logs'; +export const DEPRECATION_LOGS_INDEX = '.logs-deprecation.elasticsearch-default'; export const DEPRECATION_LOGS_INDEX_PATTERN = '.logs-deprecation.elasticsearch-default'; + +export const DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS = 60000; diff --git a/x-pack/plugins/upgrade_assistant/kibana.json b/x-pack/plugins/upgrade_assistant/kibana.json index a250ecd55f1a9..948459ca7e95f 100644 --- a/x-pack/plugins/upgrade_assistant/kibana.json +++ b/x-pack/plugins/upgrade_assistant/kibana.json @@ -10,5 +10,5 @@ "configPath": ["xpack", "upgrade_assistant"], "requiredPlugins": ["management", "discover", "data", "licensing", "features", "infra", "share"], "optionalPlugins": ["usageCollection", "cloud"], - "requiredBundles": ["esUiShared", "kibanaReact"] + "requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils"] } diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx new file mode 100644 index 0000000000000..5187e13d210bd --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useState } from 'react'; +import moment from 'moment-timezone'; +import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; + +import { i18n } from '@kbn/i18n'; +import { EuiCallOut, EuiButton, EuiLoadingContent } from '@elastic/eui'; +import { useAppContext } from '../../../../app_context'; +import { Storage } from '../../../../../shared_imports'; + +const LS_SETTING_ID = 'kibana.upgradeAssistant.lastCheckpoint'; +const localStorage = new Storage(window.localStorage); + +const i18nTexts = { + calloutTitle: (warningsCount: number, previousCheck: string) => ( + + {' '} + + + ), + }} + /> + ), + calloutBody: i18n.translate('xpack.upgradeAssistant.overview.verifyChanges.calloutBody', { + defaultMessage: + 'Reset the counter after making changes and continue monitoring to verify that you are no longer using deprecated APIs.', + }), + loadingError: i18n.translate('xpack.upgradeAssistant.overview.verifyChanges.loadingError', { + defaultMessage: 'An error occurred while retrieving the count of deprecation logs', + }), + retryButton: i18n.translate('xpack.upgradeAssistant.overview.verifyChanges.retryButton', { + defaultMessage: 'Try again', + }), + resetCounterButton: i18n.translate( + 'xpack.upgradeAssistant.overview.verifyChanges.resetCounterButton', + { + defaultMessage: 'Reset counter', + } + ), +}; + +const getPreviousCheckpointDate = () => { + const storedValue = moment(localStorage.get(LS_SETTING_ID)); + + if (storedValue.isValid()) { + return storedValue.toISOString(); + } + + const now = moment().toISOString(); + localStorage.set(LS_SETTING_ID, now); + + return now; +}; + +export const DeprecationsCountCheckpoint: FunctionComponent = () => { + const { api } = useAppContext(); + const [previousCheck, setPreviousCheck] = useState(getPreviousCheckpointDate()); + const { data, error, isLoading, resendRequest, isInitialRequest } = api.getDeprecationLogsCount( + previousCheck + ); + + const warningsCount = data?.count || 0; + const calloutTint = warningsCount > 0 ? 'warning' : 'success'; + const calloutIcon = warningsCount > 0 ? 'alert' : 'check'; + const calloutTestId = warningsCount > 0 ? 'hasWarningsCallout' : 'noWarningsCallout'; + + const onResetClick = () => { + const now = moment().toISOString(); + + setPreviousCheck(now); + localStorage.set(LS_SETTING_ID, now); + }; + + if (isInitialRequest && isLoading) { + return ; + } + + if (error) { + return ( + +

+ {error.statusCode} - {error.message} +

+ + {i18nTexts.retryButton} + +
+ ); + } + + return ( + +

{i18nTexts.calloutBody}

+ + {i18nTexts.resetCounterButton} + +
+ ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/index.ts new file mode 100644 index 0000000000000..e32655f90b848 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { DeprecationsCountCheckpoint } from './deprecations_count_checkpoint'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index 9c22a07ed771b..cc5c14a87f3da 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -12,6 +12,7 @@ import { EuiText, EuiSpacer, EuiPanel, EuiCallOut } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import { ExternalLinks } from './external_links'; +import { DeprecationsCountCheckpoint } from './deprecations_count_checkpoint'; import { useDeprecationLogging } from './use_deprecation_logging'; import { DeprecationLoggingToggle } from './deprecation_logging_toggle'; @@ -25,6 +26,12 @@ const i18nTexts = { analyzeTitle: i18n.translate('xpack.upgradeAssistant.overview.analyzeTitle', { defaultMessage: 'Analyze deprecation logs', }), + deprecationsCountCheckpointTitle: i18n.translate( + 'xpack.upgradeAssistant.overview.deprecationsCountCheckpointTitle', + { + defaultMessage: 'Resolve deprecation issues and verify your changes', + } + ), onlyLogWritingEnabledTitle: i18n.translate( 'xpack.upgradeAssistant.overview.deprecationLogs.deprecationWarningTitle', { @@ -70,11 +77,18 @@ const FixLogsStep: FunctionComponent = () => { {state.isDeprecationLogIndexingEnabled && ( <> - +

{i18nTexts.analyzeTitle}

+ + + +

{i18nTexts.deprecationsCountCheckpointTitle}

+
+ + )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index 78070c5717496..c4c1ba5e10d8a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -7,7 +7,7 @@ import { HttpSetup } from 'src/core/public'; import { ESUpgradeStatus } from '../../../common/types'; -import { API_BASE_PATH } from '../../../common/constants'; +import { API_BASE_PATH, DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS } from '../../../common/constants'; import { UseRequestConfig, SendRequestConfig, @@ -82,6 +82,17 @@ export class ApiService { return result; } + public getDeprecationLogsCount(from: string) { + return this.useRequest<{ + count: number; + }>({ + path: `${API_BASE_PATH}/deprecation_logging/count`, + method: 'get', + query: { from }, + pollIntervalMs: DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS, + }); + } + public async updateIndexSettings(indexName: string, settings: string[]) { const result = await this.sendRequest({ path: `${API_BASE_PATH}/${indexName}/index_settings`, diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index fefa6fd60f806..e9c034117038a 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -18,6 +18,8 @@ export { GlobalFlyout, } from '../../../../src/plugins/es_ui_shared/public/'; +export { Storage } from '../../../../src/plugins/kibana_utils/public'; + export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; export { DataPublicPluginStart } from '../../../../src/plugins/data/public'; diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index 870bd6b985661..a9a2671a6c713 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -32,7 +32,7 @@ import { reindexOperationSavedObjectType, mlSavedObjectType, } from './saved_object_types'; -import { DEPRECATION_LOGS_SOURCE_ID, DEPRECATION_LOGS_INDEX_PATTERN } from '../common/constants'; +import { DEPRECATION_LOGS_SOURCE_ID, DEPRECATION_LOGS_INDEX } from '../common/constants'; import { RouteDependencies } from './types'; @@ -98,7 +98,7 @@ export class UpgradeAssistantServerPlugin implements Plugin { description: 'deprecation logs', logIndices: { type: 'index_name', - indexName: DEPRECATION_LOGS_INDEX_PATTERN, + indexName: DEPRECATION_LOGS_INDEX, }, logColumns: [ { timestampColumn: { id: 'timestampField' } }, diff --git a/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/request.mock.ts b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/request.mock.ts index d3a36835d12be..c77f3a6661ebe 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/request.mock.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/request.mock.ts @@ -8,6 +8,7 @@ export const createRequestMock = (opts?: { headers?: any; params?: Record; + query?: Record; body?: Record; }) => { return Object.assign({ headers: {} }, opts || {}); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts index 1d51666dec3e5..3de96832549fb 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts @@ -62,10 +62,8 @@ describe('deprecation logging API', () => { }); it('returns an error if it throws', async () => { - ( - routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster - .getSettings as jest.Mock - ).mockRejectedValue(new Error(`scary error!`)); + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .getSettings as jest.Mock).mockRejectedValue(new Error('scary error!')); await expect( routeDependencies.router.getHandler({ method: 'get', @@ -101,10 +99,8 @@ describe('deprecation logging API', () => { }); it('returns an error if it throws', async () => { - ( - routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster - .putSettings as jest.Mock - ).mockRejectedValue(new Error(`scary error!`)); + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .putSettings as jest.Mock).mockRejectedValue(new Error('scary error!')); await expect( routeDependencies.router.getHandler({ method: 'put', @@ -113,4 +109,61 @@ describe('deprecation logging API', () => { ).rejects.toThrow('scary error!'); }); }); + + describe('GET /api/upgrade_assistant/deprecation_logging/count', () => { + const MOCK_FROM_DATE = '2021-08-23T07:32:34.782Z'; + + it('returns count of deprecations', async () => { + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices + .exists as jest.Mock).mockResolvedValue({ + body: true, + }); + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser + .count as jest.Mock).mockResolvedValue({ + body: { count: 10 }, + }); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging/count', + })( + routeHandlerContextMock, + createRequestMock({ query: { from: MOCK_FROM_DATE } }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ count: 10 }); + }); + + it('returns zero matches when deprecation logs index is not created', async () => { + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices + .exists as jest.Mock).mockResolvedValue({ + body: false, + }); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging/count', + })( + routeHandlerContextMock, + createRequestMock({ query: { from: MOCK_FROM_DATE } }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ count: 0 }); + }); + + it('returns an error if it throws', async () => { + (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices + .exists as jest.Mock).mockRejectedValue(new Error('scary error!')); + await expect( + routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/deprecation_logging/count', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory) + ).rejects.toThrow('scary error!'); + }); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts index fb2a5b559e5a9..a0dfe0d152ad5 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts @@ -14,6 +14,7 @@ import { } from '../lib/es_deprecation_logging_apis'; import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { RouteDependencies } from '../types'; +import { DEPRECATION_LOGS_INDEX } from '../../common/constants'; export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) { router.get( @@ -63,4 +64,49 @@ export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) } ) ); + + router.get( + { + path: `${API_BASE_PATH}/deprecation_logging/count`, + validate: { + query: schema.object({ + from: schema.string(), + }), + }, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { client }, + }, + }, + request, + response + ) => { + const { body: indexExists } = await client.asCurrentUser.indices.exists({ + index: DEPRECATION_LOGS_INDEX, + }); + + if (!indexExists) { + return response.ok({ body: { count: 0 } }); + } + + const { body } = await client.asCurrentUser.count({ + index: DEPRECATION_LOGS_INDEX, + body: { + query: { + range: { + '@timestamp': { + gte: request.query.from, + }, + }, + }, + }, + }); + + return response.ok({ body: { count: body.count } }); + } + ) + ); } From 7f63ad3a6bc282dc0b02febff962fee24ca58de5 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 27 Aug 2021 06:43:56 -0700 Subject: [PATCH 10/93] Add on-Cloud state to Upgrade Assistant 'Back up data' step (#109956) --- .../helpers/app_context.mock.ts | 2 +- .../upgrade_assistant/common/constants.ts | 6 + .../plugins/upgrade_assistant/common/types.ts | 5 + .../overview/backup_step/backup_step.tsx | 88 ++++-------- .../overview/backup_step/cloud_backup.tsx | 136 ++++++++++++++++++ .../overview/backup_step/on_prem_backup.tsx | 48 +++++++ .../components/overview/overview.tsx | 12 +- .../public/application/lib/api.ts | 17 ++- .../public/shared_imports.ts | 1 + .../upgrade_assistant/server/plugin.ts | 6 +- .../server/routes/cloud_backup_status.ts | 54 +++++++ .../server/routes/register_routes.ts | 2 + .../plugins/upgrade_assistant/server/types.ts | 6 +- 13 files changed, 317 insertions(+), 66 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/cloud_backup_status.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index b8d8e3d2505ef..0726b8597de2e 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -26,7 +26,7 @@ const idToUrlMap = { const shareMock = sharePluginMock.createSetupContract(); shareMock.url.locators.get = (id) => ({ // @ts-expect-error This object is missing some properties that we're not using in the UI - getUrl: (): string | undefined => idToUrlMap[id], + useUrl: (): string | undefined => idToUrlMap[id], }); export const getAppContextMock = (mockHttpClient: HttpSetup) => ({ diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index 750d5283865c8..fa55771b003d4 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -24,9 +24,15 @@ export const indexSettingDeprecations = { export const API_BASE_PATH = '/api/upgrade_assistant'; +/** + * This is the repository where Cloud stores its backup snapshots. + */ +export const CLOUD_SNAPSHOT_REPOSITORY = 'found-snapshots'; + export const DEPRECATION_WARNING_UPPER_LIMIT = 999999; export const DEPRECATION_LOGS_SOURCE_ID = 'deprecation_logs'; export const DEPRECATION_LOGS_INDEX = '.logs-deprecation.elasticsearch-default'; export const DEPRECATION_LOGS_INDEX_PATTERN = '.logs-deprecation.elasticsearch-default'; +export const CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS = 60000; export const DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS = 60000; diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index a296e158481fa..7d0f3f49f2ee5 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -215,6 +215,11 @@ export interface EnrichedDeprecationInfo resolveDuringUpgrade: boolean; } +export interface CloudBackupStatus { + isBackedUp: boolean; + lastBackupTime?: string; +} + export interface ESUpgradeStatus { totalCriticalDeprecations: number; deprecations: EnrichedDeprecationInfo[]; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx index cb5518a66a1ec..0e595dcbad1d6 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx @@ -5,72 +5,40 @@ * 2.0. */ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; -import { useAppContext } from '../../../app_context'; - -const i18nTexts = { - backupStepTitle: i18n.translate('xpack.upgradeAssistant.overview.backupStepTitle', { - defaultMessage: 'Back up your data', - }), - - backupStepDescription: i18n.translate('xpack.upgradeAssistant.overview.backupStepDescription', { - defaultMessage: 'Back up your data before addressing any deprecation warnings.', - }), -}; - -const SnapshotRestoreAppLink: React.FunctionComponent = () => { - const { share } = useAppContext(); - - const [snapshotRestoreUrl, setSnapshotRestoreUrl] = useState(); - - useEffect(() => { - const getSnapshotRestoreUrl = async () => { - const locator = share.url.locators.get('SNAPSHOT_RESTORE_LOCATOR'); - - if (!locator) { - return; - } - - const url = await locator.getUrl({ - page: 'snapshots', - }); - setSnapshotRestoreUrl(url); +import type { CloudSetup } from '../../../../../../cloud/public'; +import { OnPremBackup } from './on_prem_backup'; +import { CloudBackup, CloudBackupStatusResponse } from './cloud_backup'; + +const title = i18n.translate('xpack.upgradeAssistant.overview.backupStepTitle', { + defaultMessage: 'Back up your data', +}); + +interface Props { + cloud?: CloudSetup; + cloudBackupStatusResponse?: CloudBackupStatusResponse; +} + +export const getBackupStep = ({ cloud, cloudBackupStatusResponse }: Props): EuiStepProps => { + if (cloud?.isCloudEnabled) { + return { + title, + status: cloudBackupStatusResponse!.data?.isBackedUp ? 'complete' : 'incomplete', + children: ( + + ), }; + } - getSnapshotRestoreUrl(); - }, [share]); - - return ( - - {i18n.translate('xpack.upgradeAssistant.overview.snapshotRestoreLink', { - defaultMessage: 'Create snapshot', - })} - - ); -}; - -const BackupStep: React.FunctionComponent = () => { - return ( - <> - -

{i18nTexts.backupStepDescription}

-
- - - - - - ); -}; - -export const getBackupStep = (): EuiStepProps => { return { - title: i18nTexts.backupStepTitle, + title, status: 'incomplete', - children: , + children: , }; }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx new file mode 100644 index 0000000000000..2af9aa2e82702 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import moment from 'moment-timezone'; +import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { + EuiLoadingContent, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiText, + EuiButton, + EuiSpacer, + EuiCallOut, +} from '@elastic/eui'; + +import { CloudBackupStatus } from '../../../../../common/types'; +import { UseRequestResponse } from '../../../../shared_imports'; +import { ResponseError } from '../../../lib/api'; + +export type CloudBackupStatusResponse = UseRequestResponse; + +interface Props { + cloudBackupStatusResponse: UseRequestResponse; + cloudSnapshotsUrl: string; +} + +export const CloudBackup: React.FunctionComponent = ({ + cloudBackupStatusResponse, + cloudSnapshotsUrl, +}) => { + const { isInitialRequest, isLoading, error, data, resendRequest } = cloudBackupStatusResponse; + + if (isInitialRequest && isLoading) { + return ; + } + + if (error) { + return ( + +

+ {error.statusCode} - {error.message} +

+ + {i18n.translate('xpack.upgradeAssistant.overview.cloudBackup.retryButton', { + defaultMessage: 'Try again', + })} + +
+ ); + } + + const lastBackupTime = moment(data!.lastBackupTime).toISOString(); + + const statusMessage = data!.isBackedUp ? ( + + + + + + + +

+ + {' '} + + + ), + }} + /> +

+
+
+
+ ) : ( + + + + + + + +

+ {i18n.translate('xpack.upgradeAssistant.overview.cloudBackup.noSnapshotMessage', { + defaultMessage: `Your data isn't backed up.`, + })} +

+
+
+
+ ); + + return ( + <> + {statusMessage} + + + + + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx new file mode 100644 index 0000000000000..7982a1248b289 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; + +import { useAppContext } from '../../../app_context'; + +const SnapshotRestoreAppLink: React.FunctionComponent = () => { + const { share } = useAppContext(); + + const snapshotRestoreUrl = share.url.locators + .get('SNAPSHOT_RESTORE_LOCATOR') + ?.useUrl({ page: 'snapshots' }); + + return ( + + + + ); +}; + +export const OnPremBackup: React.FunctionComponent = () => { + return ( + <> + +

+ {i18n.translate('xpack.upgradeAssistant.overview.backupStepDescription', { + defaultMessage: 'Back up your data before addressing any deprecation issues.', + })} +

+
+ + + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index cae6a6e263550..cd5f9a4c74343 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -20,6 +20,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { useKibana } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { getBackupStep } from './backup_step'; import { getFixIssuesStep } from './fix_issues_step'; @@ -27,6 +28,9 @@ import { getFixLogsStep } from './fix_logs_step'; import { getUpgradeStep } from './upgrade_step'; export const Overview: FunctionComponent = () => { + const { + services: { cloud }, + } = useKibana(); const { kibanaVersionInfo, breadcrumbs, docLinks, api } = useAppContext(); const { nextMajor } = kibanaVersionInfo; @@ -44,6 +48,12 @@ export const Overview: FunctionComponent = () => { breadcrumbs.setBreadcrumbs('overview'); }, [breadcrumbs]); + let cloudBackupStatusResponse; + + if (cloud?.isCloudEnabled) { + cloudBackupStatusResponse = api.useLoadCloudBackupStatus(); + } + return ( @@ -84,7 +94,7 @@ export const Overview: FunctionComponent = () => { ({ + path: `${API_BASE_PATH}/cloud_backup_status`, + method: 'get', + pollIntervalMs: CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS, + }); + } + public useLoadEsDeprecations() { return this.useRequest({ path: `${API_BASE_PATH}/es_deprecations`, diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index e9c034117038a..0b606bba4fc55 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -14,6 +14,7 @@ export { SendRequestResponse, useRequest, UseRequestConfig, + UseRequestResponse, SectionLoading, GlobalFlyout, } from '../../../../src/plugins/es_ui_shared/public/'; diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index a9a2671a6c713..b47400c065bdd 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -20,6 +20,7 @@ import { InfraPluginSetup } from '../../infra/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; import { LicensingPluginSetup } from '../../licensing/server'; +import { DEPRECATION_LOGS_SOURCE_ID, DEPRECATION_LOGS_INDEX } from '../common/constants'; import { CredentialStore, credentialStoreFactory } from './lib/reindexing/credential_store'; import { ReindexWorker } from './lib/reindexing'; @@ -32,7 +33,7 @@ import { reindexOperationSavedObjectType, mlSavedObjectType, } from './saved_object_types'; -import { DEPRECATION_LOGS_SOURCE_ID, DEPRECATION_LOGS_INDEX } from '../common/constants'; +import { handleEsError } from './shared_imports'; import { RouteDependencies } from './types'; @@ -119,6 +120,9 @@ export class UpgradeAssistantServerPlugin implements Plugin { } return this.savedObjectsServiceStart; }, + lib: { + handleEsError, + }, }; // Initialize version service with current kibana version diff --git a/x-pack/plugins/upgrade_assistant/server/routes/cloud_backup_status.ts b/x-pack/plugins/upgrade_assistant/server/routes/cloud_backup_status.ts new file mode 100644 index 0000000000000..5d3ab7c854e7b --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/cloud_backup_status.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { API_BASE_PATH, CLOUD_SNAPSHOT_REPOSITORY } from '../../common/constants'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { RouteDependencies } from '../types'; + +export function registerCloudBackupStatusRoutes({ + router, + lib: { handleEsError }, +}: RouteDependencies) { + // GET most recent Cloud snapshot + router.get( + { path: `${API_BASE_PATH}/cloud_backup_status`, validate: false }, + versionCheckHandlerWrapper(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; + + try { + const { + body: { snapshots }, + } = await clusterClient.asCurrentUser.snapshot.get({ + repository: CLOUD_SNAPSHOT_REPOSITORY, + snapshot: '_all', + ignore_unavailable: true, // Allow request to succeed even if some snapshots are unavailable. + // @ts-expect-error @elastic/elasticsearch "desc" is a new param + order: 'desc', + sort: 'start_time', + size: 1, + }); + + let isBackedUp = false; + let lastBackupTime; + + if (snapshots && snapshots[0]) { + isBackedUp = true; + lastBackupTime = snapshots![0].start_time; + } + + return response.ok({ + body: { + isBackedUp, + lastBackupTime, + }, + }); + } catch (error) { + return handleEsError({ error, response }); + } + }) + ); +} diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index 332db10805692..813b25c4a79d0 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -7,6 +7,7 @@ import { RouteDependencies } from '../types'; +import { registerCloudBackupStatusRoutes } from './cloud_backup_status'; import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; import { registerReindexIndicesRoutes } from './reindex_indices'; @@ -17,6 +18,7 @@ import { ReindexWorker } from '../lib/reindexing'; import { registerUpgradeStatusRoute } from './status'; export function registerRoutes(dependencies: RouteDependencies, getWorker: () => ReindexWorker) { + registerCloudBackupStatusRoutes(dependencies); registerESDeprecationRoutes(dependencies); registerDeprecationLoggingRoutes(dependencies); registerReindexIndicesRoutes(dependencies, getWorker); diff --git a/x-pack/plugins/upgrade_assistant/server/types.ts b/x-pack/plugins/upgrade_assistant/server/types.ts index b25b73070e4cf..6c9ed3e517118 100644 --- a/x-pack/plugins/upgrade_assistant/server/types.ts +++ b/x-pack/plugins/upgrade_assistant/server/types.ts @@ -6,8 +6,9 @@ */ import { IRouter, Logger, SavedObjectsServiceStart } from 'src/core/server'; -import { CredentialStore } from './lib/reindexing/credential_store'; import { LicensingPluginSetup } from '../../licensing/server'; +import { CredentialStore } from './lib/reindexing/credential_store'; +import { handleEsError } from './shared_imports'; export interface RouteDependencies { router: IRouter; @@ -15,4 +16,7 @@ export interface RouteDependencies { log: Logger; getSavedObjectsService: () => SavedObjectsServiceStart; licensing: LicensingPluginSetup; + lib: { + handleEsError: typeof handleEsError; + }; } From 870b262022336129a3a03bc43493ad09e68f5c1e Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 30 Aug 2021 18:37:17 +0200 Subject: [PATCH 11/93] [Upgrade Assistant] Refactor external links to use locators (#110435) --- .../helpers/app_context.mock.ts | 3 +++ .../helpers/kibana_context.mock.ts | 16 -------------- .../fix_logs_step/fix_logs_step.test.tsx | 8 ++----- x-pack/plugins/upgrade_assistant/kibana.json | 2 +- .../overview/fix_logs_step/external_links.tsx | 18 ++++++++------- .../upgrade_assistant/public/plugin.ts | 22 +++++++++---------- .../plugins/upgrade_assistant/public/types.ts | 1 - 7 files changed, 27 insertions(+), 43 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index 0726b8597de2e..4cd2570f1d393 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -21,12 +21,15 @@ import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; // We'll mock these values to avoid testing the locators themselves. const idToUrlMap = { SNAPSHOT_RESTORE_LOCATOR: 'snapshotAndRestoreUrl', + DISCOVER_APP_LOCATOR: 'discoverUrl', }; const shareMock = sharePluginMock.createSetupContract(); shareMock.url.locators.get = (id) => ({ // @ts-expect-error This object is missing some properties that we're not using in the UI useUrl: (): string | undefined => idToUrlMap[id], + // @ts-expect-error This object is missing some properties that we're not using in the UI + getUrl: (): string | undefined => idToUrlMap[id], }); export const getAppContextMock = (mockHttpClient: HttpSetup) => ({ diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts index 785c8dc49a76c..043e141f4a360 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts @@ -6,25 +6,9 @@ */ import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; -import { discoverPluginMock } from '../../../../../../src/plugins/discover/public/mocks'; import { applicationServiceMock } from '../../../../../../src/core/public/application/application_service.mock'; -const discoverMock = discoverPluginMock.createStartContract(); - export const kibanaContextMock = { data: dataPluginMock.createStartContract(), application: applicationServiceMock.createStartContract(), - discover: { - ...discoverMock, - locator: { - ...discoverMock.locator, - getLocation: jest.fn(() => - Promise.resolve({ - app: '/discover', - path: 'logs', - state: {}, - }) - ), - }, - }, }; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index c19f06f03ecc2..dec34ba1e3720 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -151,11 +151,7 @@ describe('Overview - Fix deprecation logs step', () => { test('Has a link to see logs in discover app', async () => { await act(async () => { - testBed = await setupOverviewPage({ - getUrlForApp: jest.fn((app, options) => { - return `${app}/${options.path}`; - }), - }); + testBed = await setupOverviewPage(); }); const { exists, component, find } = testBed; @@ -163,7 +159,7 @@ describe('Overview - Fix deprecation logs step', () => { component.update(); expect(exists('viewDiscoverLogs')).toBe(true); - expect(find('viewDiscoverLogs').props().href).toBe('/discover/logs'); + expect(find('viewDiscoverLogs').props().href).toBe('discoverUrl'); }); }); diff --git a/x-pack/plugins/upgrade_assistant/kibana.json b/x-pack/plugins/upgrade_assistant/kibana.json index 948459ca7e95f..4573be8fdc041 100644 --- a/x-pack/plugins/upgrade_assistant/kibana.json +++ b/x-pack/plugins/upgrade_assistant/kibana.json @@ -8,7 +8,7 @@ "githubTeam": "kibana-stack-management" }, "configPath": ["xpack", "upgrade_assistant"], - "requiredPlugins": ["management", "discover", "data", "licensing", "features", "infra", "share"], + "requiredPlugins": ["management", "data", "licensing", "features", "infra", "share"], "optionalPlugins": ["usageCollection", "cloud"], "requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils"] } diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx index 0cd5ad5bfdb2f..7ddd1c562ac3f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx @@ -39,24 +39,26 @@ const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) }; const DiscoverAppLink: FunctionComponent = () => { - const { getUrlForApp } = useAppContext(); - const { data: dataService, discover: discoverService } = useKibana().services; + const { share } = useAppContext(); + const { data: dataService } = useKibana().services; const [discoveryUrl, setDiscoveryUrl] = useState(); useEffect(() => { const getDiscoveryUrl = async () => { const indexPatternId = await getDeprecationIndexPatternId(dataService); - const appLocation = await discoverService?.locator?.getLocation({ indexPatternId }); + const locator = share.url.locators.get('DISCOVER_APP_LOCATOR'); - const result = getUrlForApp(appLocation?.app as string, { - path: appLocation?.path, - }); - setDiscoveryUrl(result); + if (!locator) { + return; + } + + const url = await locator.getUrl({ indexPatternId }); + setDiscoveryUrl(url); }; getDiscoveryUrl(); - }, [dataService, discoverService, getUrlForApp]); + }, [dataService, share.url.locators]); return ( diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index bb6bf35029959..0a6fc1d30c5cd 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -42,19 +42,19 @@ export class UpgradeAssistantUIPlugin values: { version: `${kibanaVersionInfo.nextMajor}.0` }, }); - appRegistrar.registerApp({ - id: 'upgrade_assistant', - title: pluginName, - order: 1, - async mount(params) { - const [coreStart, { discover, data }] = await coreSetup.getStartServices(); - const services: AppServicesContext = { discover, data, cloud }; + appRegistrar.registerApp({ + id: 'upgrade_assistant', + title: pluginName, + order: 1, + async mount(params) { + const [coreStart, { data }] = await coreSetup.getStartServices(); + const services: AppServicesContext = { data, cloud }; - const { - chrome: { docTitle }, - } = coreStart; + const { + chrome: { docTitle }, + } = coreStart; - docTitle.change(pluginName); + docTitle.change(pluginName); const { mountManagementSection } = await import('./application/mount_management_section'); const unmountAppCallback = await mountManagementSection( diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index b07f0dbc7c206..9cd9ba856ffb0 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -13,7 +13,6 @@ import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; export interface AppServicesContext { - discover: DiscoverStart; data: DataPublicPluginStart; cloud?: CloudSetup; } From 755eef80281a0bd1f6c09c38870a2e8c7386e325 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 31 Aug 2021 11:56:11 +0200 Subject: [PATCH 12/93] [Upgrade Assistant] Use AppContext for services instead of KibanaContext (#109801) * Remove kibana context dependency in favour of app context * Add missing type to ContextValue * Fix mock type * Refactor app mount flow and types * Refactor to use useServices hook * Fix linter issues * Keep mount_management_section and initialize breadcrumbs and api there * Remove useServices and usePlugins in favour of just useAppContext * Remove unnecessary mocks --- .../helpers/app_context.mock.ts | 43 +++++++++---- .../helpers/kibana_context.mock.ts | 14 ----- .../helpers/setup_environment.tsx | 40 ++++++------- .../kibana_deprecations.test.ts | 18 +++++- .../fix_issues_step/fix_issues_step.test.tsx | 18 +++++- .../upgrade_step/upgrade_step.test.tsx | 2 +- .../public/application/app.tsx | 40 +++++-------- .../public/application/app_context.tsx | 34 +---------- .../components/coming_soon_prompt.tsx | 8 ++- .../index_settings/table_row.tsx | 4 +- .../ml_snapshots/table_row.tsx | 4 +- .../reindex/flyout/container.tsx | 6 +- .../reindex/flyout/warning_step.test.tsx | 6 +- .../reindex/flyout/warnings_step.tsx | 6 +- .../deprecation_types/reindex/table_row.tsx | 8 ++- .../es_deprecations/es_deprecations.tsx | 4 +- .../kibana_deprecations.tsx | 8 ++- .../overview/backup_step/on_prem_backup.tsx | 4 +- .../fix_issues_step/es_stats/es_stats.tsx | 4 +- .../kibana_stats/kibana_stats.tsx | 6 +- .../deprecations_count_checkpoint.tsx | 4 +- .../overview/fix_logs_step/external_links.tsx | 18 ++++-- .../fix_logs_step/use_deprecation_logging.ts | 7 ++- .../components/overview/overview.tsx | 13 ++-- .../overview/upgrade_step/upgrade_step.tsx | 6 +- .../application/mount_management_section.tsx | 60 ++++--------------- .../upgrade_assistant/public/plugin.ts | 38 +++++++----- .../public/shared_imports.ts | 5 -- .../plugins/upgrade_assistant/public/types.ts | 28 ++++++++- 29 files changed, 247 insertions(+), 209 deletions(-) delete mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index 4cd2570f1d393..7550055d8242d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -10,13 +10,23 @@ import { docLinksServiceMock, notificationServiceMock, applicationServiceMock, + httpServiceMock, + coreMock, + scopedHistoryMock, } from 'src/core/public/mocks'; import { sharePluginMock } from 'src/plugins/share/public/mocks'; -import { HttpSetup } from 'src/core/public'; import { mockKibanaSemverVersion } from '../../../common/constants'; import { apiService } from '../../../public/application/lib/api'; import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; +import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; +import { cloudMock } from '../../../../../../x-pack/plugins/cloud/public/mocks'; + +const servicesMock = { + api: apiService, + breadcrumbs: breadcrumbService, + data: dataPluginMock.createStartContract(), +}; // We'll mock these values to avoid testing the locators themselves. const idToUrlMap = { @@ -32,19 +42,30 @@ shareMock.url.locators.get = (id) => ({ getUrl: (): string | undefined => idToUrlMap[id], }); -export const getAppContextMock = (mockHttpClient: HttpSetup) => ({ - http: mockHttpClient, - docLinks: docLinksServiceMock.createStartContract(), +export const getAppContextMock = () => ({ + isReadOnlyMode: false, kibanaVersionInfo: { currentMajor: mockKibanaSemverVersion.major, prevMajor: mockKibanaSemverVersion.major - 1, nextMajor: mockKibanaSemverVersion.major + 1, }, - notifications: notificationServiceMock.createStartContract(), - isReadOnlyMode: false, - api: apiService, - breadcrumbs: breadcrumbService, - getUrlForApp: applicationServiceMock.createStartContract().getUrlForApp, - deprecations: deprecationsServiceMock.createStartContract(), - share: shareMock, + services: { + ...servicesMock, + core: { + ...coreMock.createStart(), + http: httpServiceMock.createSetupContract(), + deprecations: deprecationsServiceMock.createStartContract(), + notifications: notificationServiceMock.createStartContract(), + docLinks: docLinksServiceMock.createStartContract(), + history: scopedHistoryMock.create(), + application: applicationServiceMock.createStartContract(), + }, + }, + plugins: { + share: shareMock, + cloud: { + ...cloudMock.createSetup(), + isCloudEnabled: false, + }, + }, }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts deleted file mode 100644 index 043e141f4a360..0000000000000 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_context.mock.ts +++ /dev/null @@ -1,14 +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 { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; -import { applicationServiceMock } from '../../../../../../src/core/public/application/application_service.mock'; - -export const kibanaContextMock = { - data: dataPluginMock.createStartContract(), - application: applicationServiceMock.createStartContract(), -}; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx index f5b0993a2267f..e9104ea2d75a4 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx @@ -8,20 +8,20 @@ import React from 'react'; import axios from 'axios'; import SemVer from 'semver/classes/semver'; +import { merge } from 'lodash'; // @ts-ignore import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { MAJOR_VERSION } from '../../../common/constants'; import { HttpSetup } from 'src/core/public'; -import { KibanaContextProvider } from '../../../public/shared_imports'; import { AppContextProvider } from '../../../public/application/app_context'; import { apiService } from '../../../public/application/lib/api'; import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; import { GlobalFlyout } from '../../../public/shared_imports'; -import { kibanaContextMock } from './kibana_context.mock'; import { getAppContextMock } from './app_context.mock'; import { init as initHttpRequests } from './http_requests'; +import { AppDependencies } from '../../../public/types'; const { GlobalFlyoutProvider } = GlobalFlyout; @@ -29,26 +29,22 @@ const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); export const kibanaVersion = new SemVer(MAJOR_VERSION); -export const WithAppDependencies = - (Comp: any, overrides: Record = {}) => - (props: Record) => { - apiService.setup(mockHttpClient as unknown as HttpSetup); - breadcrumbService.setup(() => ''); - - const appContextMock = getAppContextMock(mockHttpClient as unknown as HttpSetup); - - const { kibanaContextOverrides, ...appContextOverrides } = overrides; - - return ( - - - - - - - - ); - }; +export const WithAppDependencies = (Comp: any, overrides: Record = {}) => ( + props: Record +) => { + apiService.setup((mockHttpClient as unknown) as HttpSetup); + breadcrumbService.setup(() => ''); + + const appContextMock = (getAppContextMock() as unknown) as AppDependencies; + + return ( + + + + + + ); +}; export const setupEnvironment = () => { const { server, httpRequestsMockHelpers } = initHttpRequests(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts index 503b5715b45b3..7ac2b28ada5e0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts @@ -45,7 +45,11 @@ describe('Kibana deprecations', () => { .mockReturnValue(kibanaDeprecationsMockResponse); testBed = await setupKibanaPage({ - deprecations: deprecationService, + services: { + core: { + deprecations: deprecationService, + }, + }, }); }); @@ -177,7 +181,11 @@ describe('Kibana deprecations', () => { .mockRejectedValue(new Error('Internal Server Error')); testBed = await setupKibanaPage({ - deprecations: deprecationService, + services: { + core: { + deprecations: deprecationService, + }, + }, }); }); @@ -210,7 +218,11 @@ describe('Kibana deprecations', () => { .mockReturnValue(kibanaDeprecationsMockResponse); testBed = await setupKibanaPage({ - deprecations: deprecationService, + services: { + core: { + deprecations: deprecationService, + }, + }, }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx index 581e80e7c290a..e39f0da488205 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx @@ -26,7 +26,11 @@ describe('Overview - Fix deprecation issues step', () => { .mockReturnValue(mockedResponses.kibanaDeprecations); testBed = await setupOverviewPage({ - deprecations: deprecationService, + services: { + core: { + deprecations: deprecationService, + }, + }, }); }); @@ -172,7 +176,11 @@ describe('Overview - Fix deprecation issues step', () => { deprecationService.getAllDeprecations = jest.fn().mockRejectedValue([]); testBed = await setupOverviewPage({ - deprecations: deprecationService, + services: { + core: { + deprecations: deprecationService, + }, + }, }); }); @@ -201,7 +209,11 @@ describe('Overview - Fix deprecation issues step', () => { .mockRejectedValue(new Error('Internal Server Error')); testBed = await setupOverviewPage({ - deprecations: deprecationService, + services: { + core: { + deprecations: deprecationService, + }, + }, }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx index 61fc6b45fa4c7..7135c5849fb73 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx @@ -36,7 +36,7 @@ describe('Overview - Upgrade Step', () => { test('Shows upgrade CTA and link to docs', async () => { await act(async () => { testBed = await setupOverviewPage({ - kibanaContextOverrides: { + plugins: { cloud: { isCloudEnabled: true, deploymentUrl: diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index 8a1ee9a91cabb..cc921bdaefc15 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -7,26 +7,19 @@ import React from 'react'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; -import { I18nStart, ScopedHistory } from 'src/core/public'; -import { ApplicationStart } from 'kibana/public'; +import { ScopedHistory } from 'src/core/public'; import { GlobalFlyout } from '../shared_imports'; -import { KibanaContextProvider, APP_WRAPPER_CLASS } from '../shared_imports'; -import { AppServicesContext } from '../types'; -import { AppContextProvider, ContextValue, useAppContext } from './app_context'; +import { APP_WRAPPER_CLASS } from '../shared_imports'; +import { AppContextProvider, useAppContext } from './app_context'; import { ComingSoonPrompt } from './components/coming_soon_prompt'; import { EsDeprecations } from './components/es_deprecations'; import { KibanaDeprecationsContent } from './components/kibana_deprecations'; import { Overview } from './components/overview'; import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; +import { AppDependencies } from '../types'; const { GlobalFlyoutProvider } = GlobalFlyout; -export interface AppDependencies extends ContextValue { - i18n: I18nStart; - history: ScopedHistory; - application: ApplicationStart; - services: AppServicesContext; -} const App: React.FunctionComponent = () => { const { isReadOnlyMode } = useAppContext(); @@ -54,23 +47,20 @@ export const AppWithRouter = ({ history }: { history: ScopedHistory }) => { ); }; -export const RootComponent = ({ - i18n, - history, - services, - application, - ...contextValue -}: AppDependencies) => { +export const RootComponent = (dependencies: AppDependencies) => { + const { + history, + core: { i18n, application }, + } = dependencies.services; + return ( - - - - - - - + + + + + ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx index 9543c1c4db385..8b11b20ed1853 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx @@ -6,44 +6,16 @@ */ import React, { createContext, useContext } from 'react'; -import { - CoreStart, - DeprecationsServiceStart, - DocLinksStart, - HttpSetup, - NotificationsStart, -} from 'src/core/public'; -import { SharePluginSetup } from 'src/plugins/share/public'; -import { ApiService } from './lib/api'; -import { BreadcrumbService } from './lib/breadcrumbs'; +import { AppDependencies } from '../types'; -export interface KibanaVersionContext { - currentMajor: number; - prevMajor: number; - nextMajor: number; -} - -export interface ContextValue { - http: HttpSetup; - docLinks: DocLinksStart; - kibanaVersionInfo: KibanaVersionContext; - notifications: NotificationsStart; - isReadOnlyMode: boolean; - api: ApiService; - breadcrumbs: BreadcrumbService; - getUrlForApp: CoreStart['application']['getUrlForApp']; - deprecations: DeprecationsServiceStart; - share: SharePluginSetup; -} - -export const AppContext = createContext({} as any); +export const AppContext = createContext(undefined); export const AppContextProvider = ({ children, value, }: { children: React.ReactNode; - value: ContextValue; + value: AppDependencies; }) => { return {children}; }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx index 14627f0b138b0..883a8675e0ce0 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/coming_soon_prompt.tsx @@ -11,7 +11,13 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { useAppContext } from '../app_context'; export const ComingSoonPrompt: React.FunctionComponent = () => { - const { kibanaVersionInfo, docLinks } = useAppContext(); + const { + kibanaVersionInfo, + services: { + core: { docLinks }, + }, + } = useAppContext(); + const { nextMajor, currentMajor } = kibanaVersionInfo; const { ELASTIC_WEBSITE_URL } = docLinks; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx index b118d01a2d540..d7e940b96e605 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx @@ -33,7 +33,9 @@ export const IndexSettingsTableRow: React.FunctionComponent = ({ details?: ResponseError; }>({ statusType: 'idle' }); - const { api } = useAppContext(); + const { + services: { api }, + } = useAppContext(); const { addContent: addContentToGlobalFlyout, removeContent: removeContentFromGlobalFlyout } = useGlobalFlyout(); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx index 9d961aed8ffc9..e4221eb10a554 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx @@ -76,7 +76,9 @@ export const MlSnapshotsTableRowCells: React.FunctionComponent = }; export const MlSnapshotsTableRow: React.FunctionComponent = (props) => { - const { api } = useAppContext(); + const { + services: { api }, + } = useAppContext(); return ( = ({ }) => { const { status, reindexWarnings } = reindexState; const { index, correctiveAction } = deprecation; - const { docLinks } = useAppContext(); + const { + services: { + core: { docLinks }, + }, + } = useAppContext(); // If there are any warnings and we haven't started reindexing, show the warnings step first. const [currentFlyoutStep, setCurrentFlyoutStep] = useState( reindexWarnings && reindexWarnings.length > 0 && status === undefined diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx index d2cafd69e94eb..287048d8f257e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx @@ -30,8 +30,12 @@ jest.mock('../../../../../app_context', () => { return { useAppContext: () => { return { - docLinks: docLinksServiceMock.createStartContract(), kibanaVersionInfo: mockKibanaVersionInfo, + services: { + core: { + docLinks: docLinksServiceMock.createStartContract(), + }, + }, }; }, }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx index 4415811f6bf38..9e3755bfa8a35 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx @@ -56,7 +56,11 @@ export const WarningsFlyoutStep: React.FunctionComponent { - const { docLinks } = useAppContext(); + const { + services: { + core: { docLinks }, + }, + } = useAppContext(); const { links } = docLinks; const [checkedIds, setCheckedIds] = useState( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx index 1cf555b6cb340..29c190f015f3c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx @@ -29,7 +29,9 @@ const ReindexTableRowCells: React.FunctionComponent = ({ }) => { const [showFlyout, setShowFlyout] = useState(false); const reindexState = useReindexContext(); - const { api } = useAppContext(); + const { + services: { api }, + } = useAppContext(); const { addContent: addContentToGlobalFlyout, removeContent: removeContentFromGlobalFlyout } = useGlobalFlyout(); @@ -92,7 +94,9 @@ const ReindexTableRowCells: React.FunctionComponent = ({ }; export const ReindexTableRow: React.FunctionComponent = (props) => { - const { api } = useAppContext(); + const { + services: { api }, + } = useAppContext(); return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index b714ae2ca2fd1..52722a52be6d3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -71,7 +71,9 @@ const i18nTexts = { }; export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { - const { api, breadcrumbs } = useAppContext(); + const { + services: { api, breadcrumbs }, + } = useAppContext(); const { data: esDeprecations, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 56d6e23d9d4f3..90f8936d0e38d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -64,7 +64,13 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent >(undefined); const [isResolvingDeprecation, setIsResolvingDeprecation] = useState(false); - const { deprecations, breadcrumbs, docLinks, api, notifications } = useAppContext(); + const { + services: { + core: { deprecations, docLinks, notifications }, + breadcrumbs, + api, + }, + } = useAppContext(); const getAllDeprecations = useCallback(async () => { setIsLoading(true); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx index 7982a1248b289..2e2e2bd5ce48e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx @@ -13,7 +13,9 @@ import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; const SnapshotRestoreAppLink: React.FunctionComponent = () => { - const { share } = useAppContext(); + const { + plugins: { share }, + } = useAppContext(); const snapshotRestoreUrl = share.url.locators .get('SNAPSHOT_RESTORE_LOCATOR') diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx index ef0b3f438da03..9526f5bc2316c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx @@ -62,7 +62,9 @@ const i18nTexts = { export const ESDeprecationStats: FunctionComponent = () => { const history = useHistory(); - const { api } = useAppContext(); + const { + services: { api }, + } = useAppContext(); const { data: esDeprecations, isLoading, error } = api.useLoadEsDeprecations(); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx index d7b820aa4a484..9388ee52f57a1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx @@ -70,7 +70,11 @@ const i18nTexts = { export const KibanaDeprecationStats: FunctionComponent = () => { const history = useHistory(); - const { deprecations } = useAppContext(); + const { + services: { + core: { deprecations }, + }, + } = useAppContext(); const [kibanaDeprecations, setKibanaDeprecations] = useState< DomainDeprecationDetails[] | undefined diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx index 5187e13d210bd..58b7b7ca11ebd 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -65,7 +65,9 @@ const getPreviousCheckpointDate = () => { }; export const DeprecationsCountCheckpoint: FunctionComponent = () => { - const { api } = useAppContext(); + const { + services: { api }, + } = useAppContext(); const [previousCheck, setPreviousCheck] = useState(getPreviousCheckpointDate()); const { data, error, isLoading, resendRequest, isInitialRequest } = api.getDeprecationLogsCount( previousCheck diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx index 7ddd1c562ac3f..5afd1dba32c3a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx @@ -11,7 +11,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiLink, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiPanel, EuiText } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; -import { useKibana, DataPublicPluginStart } from '../../../../shared_imports'; +import { DataPublicPluginStart } from '../../../../shared_imports'; import { DEPRECATION_LOGS_INDEX_PATTERN, DEPRECATION_LOGS_SOURCE_ID, @@ -39,8 +39,10 @@ const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) }; const DiscoverAppLink: FunctionComponent = () => { - const { share } = useAppContext(); - const { data: dataService } = useKibana().services; + const { + services: { data: dataService }, + plugins: { share }, + } = useAppContext(); const [discoveryUrl, setDiscoveryUrl] = useState(); @@ -61,7 +63,7 @@ const DiscoverAppLink: FunctionComponent = () => { }, [dataService, share.url.locators]); return ( - + { }; const ObservabilityAppLink: FunctionComponent = () => { - const { http } = useAppContext(); + const { + services: { + core: { http }, + }, + } = useAppContext(); const logStreamUrl = http?.basePath?.prepend( `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}` ); return ( - + { - const { api, notifications } = useAppContext(); + const { + services: { + api, + core: { notifications }, + }, + } = useAppContext(); const { data, error: fetchError, isLoading, resendRequest } = api.useLoadDeprecationLogging(); const [isDeprecationLogIndexingEnabled, setIsDeprecationLogIndexingEnabled] = useState(false); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index cd5f9a4c74343..4ab5109bd996c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -20,7 +20,6 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { useKibana } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { getBackupStep } from './backup_step'; import { getFixIssuesStep } from './fix_issues_step'; @@ -29,10 +28,14 @@ import { getUpgradeStep } from './upgrade_step'; export const Overview: FunctionComponent = () => { const { - services: { cloud }, - } = useKibana(); - const { kibanaVersionInfo, breadcrumbs, docLinks, api } = useAppContext(); - const { nextMajor } = kibanaVersionInfo; + kibanaVersionInfo: { nextMajor }, + services: { + breadcrumbs, + api, + core: { docLinks }, + }, + plugins: { cloud }, + } = useAppContext(); useEffect(() => { async function sendTelemetryData() { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx index 49c81a117d612..cb8c88b9d2af2 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx @@ -18,7 +18,7 @@ import { import { i18n } from '@kbn/i18n'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import type { DocLinksStart } from 'src/core/public'; -import { useKibana } from '../../../../shared_imports'; +import { useAppContext } from '../../../app_context'; const i18nTexts = { upgradeStepTitle: (nextMajor: number) => @@ -49,7 +49,9 @@ const i18nTexts = { }; const UpgradeStep = ({ docLinks }: { docLinks: DocLinksStart }) => { - const { cloud } = useKibana().services; + const { + plugins: { cloud }, + } = useAppContext(); const isCloudEnabled: boolean = Boolean(cloud?.isCloudEnabled); let callToAction; diff --git a/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.tsx b/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.tsx index d3f5cb07659c5..6ab764ddcba6d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.tsx @@ -7,60 +7,26 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { CoreSetup } from 'src/core/public'; -import { ManagementAppMountParams } from 'src/plugins/management/public'; -import { SharePluginSetup } from 'src/plugins/share/public'; -import { KibanaVersionContext } from './app_context'; -import { AppDependencies, RootComponent } from './app'; +import type { ManagementAppMountParams } from 'src/plugins/management/public'; +import { RootComponent } from './app'; +import { AppDependencies } from '../types'; + import { apiService } from './lib/api'; import { breadcrumbService } from './lib/breadcrumbs'; -import { AppServicesContext } from '../types'; - -interface BootDependencies extends AppDependencies { - element: HTMLElement; -} - -const renderApp = (deps: BootDependencies) => { - const { element, ...appDependencies } = deps; - render(, element); - return () => { - unmountComponentAtNode(element); - }; -}; -export async function mountManagementSection( - coreSetup: CoreSetup, +export function mountManagementSection( params: ManagementAppMountParams, - kibanaVersionInfo: KibanaVersionContext, - readonly: boolean, - share: SharePluginSetup, - services: AppServicesContext + dependencies: AppDependencies ) { - const [{ i18n, docLinks, notifications, application, deprecations }] = - await coreSetup.getStartServices(); - - const { element, history, setBreadcrumbs } = params; - const { http } = coreSetup; + const { element, setBreadcrumbs } = params; - apiService.setup(http); + apiService.setup(dependencies.services.core.http); breadcrumbService.setup(setBreadcrumbs); - return renderApp({ - element, - http, - i18n, - docLinks, - kibanaVersionInfo, - notifications, - isReadOnlyMode: readonly, - history, - api: apiService, - breadcrumbs: breadcrumbService, - getUrlForApp: application.getUrlForApp, - deprecations, - application, - share, - services, - }); + render(, element); + + return () => { + unmountComponentAtNode(element); + }; } diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index 0a6fc1d30c5cd..03e5c91c99daa 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -9,12 +9,9 @@ import SemVer from 'semver/classes/semver'; import { i18n } from '@kbn/i18n'; import { Plugin, CoreSetup, PluginInitializerContext } from 'src/core/public'; -import { - SetupDependencies, - StartDependencies, - AppServicesContext, - ClientConfigType, -} from './types'; +import { apiService } from './application/lib/api'; +import { breadcrumbService } from './application/lib/breadcrumbs'; +import { SetupDependencies, StartDependencies, AppDependencies, ClientConfigType } from './types'; export class UpgradeAssistantUIPlugin implements Plugin @@ -47,8 +44,7 @@ export class UpgradeAssistantUIPlugin title: pluginName, order: 1, async mount(params) { - const [coreStart, { data }] = await coreSetup.getStartServices(); - const services: AppServicesContext = { data, cloud }; + const [coreStart, { discover, data }] = await coreSetup.getStartServices(); const { chrome: { docTitle }, @@ -56,15 +52,25 @@ export class UpgradeAssistantUIPlugin docTitle.change(pluginName); - const { mountManagementSection } = await import('./application/mount_management_section'); - const unmountAppCallback = await mountManagementSection( - coreSetup, - params, + const appDependencies: AppDependencies = { kibanaVersionInfo, - readonly, - share, - services - ); + isReadOnlyMode: readonly, + plugins: { + cloud, + share, + }, + services: { + core: coreStart, + data, + history: params.history, + discover, + api: apiService, + breadcrumbs: breadcrumbService, + }, + }; + + const { mountManagementSection } = await import('./application/mount_management_section'); + const unmountAppCallback = mountManagementSection(params, appDependencies); return () => { docTitle.reset(); diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index 0b606bba4fc55..706732aa0027b 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -5,9 +5,6 @@ * 2.0. */ -import { useKibana as _useKibana } from '../../../../src/plugins/kibana_react/public'; -import { AppServicesContext } from './types'; - export { sendRequest, SendRequestConfig, @@ -26,5 +23,3 @@ export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/publ export { DataPublicPluginStart } from '../../../../src/plugins/data/public'; export { APP_WRAPPER_CLASS } from '../../../../src/core/public'; - -export const useKibana = () => _useKibana(); diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index 9cd9ba856ffb0..8b5ac002c25ac 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -5,16 +5,21 @@ * 2.0. */ +import { ScopedHistory } from 'kibana/public'; import { DiscoverStart } from 'src/plugins/discover/public'; import { ManagementSetup } from 'src/plugins/management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SharePluginSetup } from 'src/plugins/share/public'; +import { CoreStart } from 'src/core/public'; import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; +import { BreadcrumbService } from './application/lib/breadcrumbs'; +import { ApiService } from './application/lib/api'; -export interface AppServicesContext { - data: DataPublicPluginStart; - cloud?: CloudSetup; +export interface KibanaVersionContext { + currentMajor: number; + prevMajor: number; + nextMajor: number; } export interface SetupDependencies { @@ -35,3 +40,20 @@ export interface ClientConfigType { enabled: boolean; }; } + +export interface AppDependencies { + isReadOnlyMode: boolean; + kibanaVersionInfo: KibanaVersionContext; + plugins: { + cloud?: CloudSetup; + share: SharePluginSetup; + }; + services: { + core: CoreStart; + discover: DiscoverStart; + data: DataPublicPluginStart; + breadcrumbs: BreadcrumbService; + history: ScopedHistory; + api: ApiService; + }; +} From df4c3af83b2e9938cbcc1412a315d224c97cbf10 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 31 Aug 2021 12:01:00 -0400 Subject: [PATCH 13/93] [Upgrade Assistant] Enable functional and a11y tests (#109909) --- .../es_deprecations/es_deprecations_table.tsx | 2 +- .../components/overview/overview.tsx | 2 +- .../accessibility/apps/upgrade_assistant.ts | 115 ++++++++++-------- .../upgrade_assistant_security.ts | 6 - .../apps/upgrade_assistant/index.ts | 2 +- .../upgrade_assistant/upgrade_assistant.ts | 110 +++++++++++------ x-pack/test/functional/config.js | 8 +- .../page_objects/upgrade_assistant_page.ts | 43 +------ 8 files changed, 150 insertions(+), 138 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx index 956700319b2b4..30866e9299f34 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx @@ -261,7 +261,7 @@ export const EsDeprecationsTable: React.FunctionComponent = ({ - + {Object.entries(cellToLabelMap).map(([fieldName, cell]) => { return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index 4ab5109bd996c..1c11bc165d931 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -58,7 +58,7 @@ export const Overview: FunctionComponent = () => { } return ( - + { before(async () => { await PageObjects.upgradeAssistant.navigateToPage(); + try { + // Create an index that will trigger a deprecation warning to test the ES deprecations page + await es.indices.create(translogSettingsIndexDeprecation); + } catch (e) { + log.debug('[Setup error] Error creating index'); + throw e; + } }); - // These tests will be skipped until the last minor of the next major release - describe('Upgrade Assistant content', () => { - it('Overview page', async () => { - await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { - return testSubjects.exists('overviewPageContent'); - }); - await a11y.testAppSnapshot(); - }); - - it('Elasticsearch cluster deprecations', async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/es_deprecations/cluster', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); - - await retry.waitFor('Cluster tab to be visible', async () => { - return testSubjects.exists('clusterTabContent'); + after(async () => { + try { + await es.indices.delete({ + index: [translogSettingsIndexDeprecation.index], }); + } catch (e) { + log.debug('[Cleanup error] Error deleting index'); + throw e; + } + }); - await a11y.testAppSnapshot(); + it('Overview page', async () => { + await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { + return testSubjects.exists('overview'); }); + await a11y.testAppSnapshot(); + }); - it('Elasticsearch index deprecations', async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/es_deprecations/indices', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); - - await retry.waitFor('Indices tab to be visible', async () => { - return testSubjects.exists('indexTabContent'); - }); + it('Elasticsearch deprecations page', async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/es_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); - await a11y.testAppSnapshot(); + await retry.waitFor('Elasticsearch deprecations table to be visible', async () => { + return testSubjects.exists('esDeprecationsTable'); }); - it('Kibana deprecations', async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/kibana_deprecations', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); + await a11y.testAppSnapshot(); + }); - await retry.waitFor('Kibana deprecations to be visible', async () => { - return testSubjects.exists('kibanaDeprecationsContent'); - }); + it('Kibana deprecations page', async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/kibana_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); - await a11y.testAppSnapshot(); + await retry.waitFor('Kibana deprecations to be visible', async () => { + return testSubjects.exists('kibanaDeprecationsContent'); }); + + await a11y.testAppSnapshot(); }); }); } diff --git a/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts b/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts index 7aa8bfe4eff69..dca3391ae5463 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts @@ -9,7 +9,6 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); const security = getService('security'); const PageObjects = getPageObjects(['common', 'settings', 'security']); const appsMenu = getService('appsMenu'); @@ -17,14 +16,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe.skip('security', function () { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); await PageObjects.common.navigateToApp('home'); }); - after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana'); - }); - describe('global all privileges (aka kibana_admin)', () => { before(async () => { await security.testUser.setRoles(['kibana_admin'], true); diff --git a/x-pack/test/functional/apps/upgrade_assistant/index.ts b/x-pack/test/functional/apps/upgrade_assistant/index.ts index c25e0af414397..cacf55c58dce2 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/index.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/index.ts @@ -8,7 +8,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function upgradeCheckup({ loadTestFile }: FtrProviderContext) { - describe('Upgrade checkup ', function upgradeAssistantTestSuite() { + describe('Upgrade Assistant', function upgradeAssistantTestSuite() { this.tags('ciGroup4'); loadTestFile(require.resolve('./feature_controls')); diff --git a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts index 93475c228ed2f..fec341de6c09e 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts @@ -5,75 +5,109 @@ * 2.0. */ -import expect from '@kbn/expect'; +import { IndicesCreateRequest } from '@elastic/elasticsearch/api/types'; import { FtrProviderContext } from '../../ftr_provider_context'; +const multiFieldsIndexDeprecation: IndicesCreateRequest = { + index: 'nested_multi_fields', + body: { + mappings: { + properties: { + text: { + type: 'text', + fields: { + english: { + type: 'text', + analyzer: 'english', + fields: { + english: { + type: 'text', + analyzer: 'english', + }, + }, + }, + }, + }, + }, + }, + }, +}; + +const translogSettingsIndexDeprecation: IndicesCreateRequest = { + index: 'deprecated_settings', + body: { + settings: { + 'translog.retention.size': '1b', + 'translog.retention.age': '5m', + 'index.soft_deletes.enabled': true, + }, + }, +}; + export default function upgradeAssistantFunctionalTests({ getService, getPageObjects, }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['upgradeAssistant', 'common']); + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + const es = getService('es'); const security = getService('security'); const log = getService('log'); - const retry = getService('retry'); // Updated for the hiding of the UA UI. describe.skip('Upgrade Checkup', function () { this.tags('skipFirefox'); before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); await security.testUser.setRoles(['global_upgrade_assistant_role']); + + try { + // Create two indices that will trigger deprecation warnings to test the ES deprecations page + await es.indices.create(multiFieldsIndexDeprecation); + await es.indices.create(translogSettingsIndexDeprecation); + } catch (e) { + log.debug('[Setup error] Error creating indices'); + throw e; + } }); after(async () => { - await PageObjects.upgradeAssistant.waitForTelemetryHidden(); - await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana'); + try { + await es.indices.delete({ + index: [multiFieldsIndexDeprecation.index, translogSettingsIndexDeprecation.index], + }); + } catch (e) { + log.debug('[Cleanup error] Error deleting indices'); + throw e; + } + await security.testUser.restoreDefaults(); }); - it.skip('allows user to navigate to upgrade checkup', async () => { + it('renders the Overview page', async () => { await PageObjects.upgradeAssistant.navigateToPage(); + await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { + return testSubjects.exists('overview'); + }); }); - it.skip('allows user to toggle deprecation logging', async () => { - log.debug('expect initial state to be ON'); - expect(await PageObjects.upgradeAssistant.deprecationLoggingEnabledLabel()).to.be('On'); - expect(await PageObjects.upgradeAssistant.isDeprecationLoggingEnabled()).to.be(true); - - await retry.try(async () => { - log.debug('Now toggle to off'); - await PageObjects.upgradeAssistant.toggleDeprecationLogging(); - - log.debug('expect state to be OFF after toggle'); - expect(await PageObjects.upgradeAssistant.isDeprecationLoggingEnabled()).to.be(false); - expect(await PageObjects.upgradeAssistant.deprecationLoggingEnabledLabel()).to.be('Off'); - }); + it('renders the Elasticsearch deprecations page', async () => { + await PageObjects.upgradeAssistant.navigateToPage(); + await PageObjects.upgradeAssistant.clickEsDeprecationsPanel(); - log.debug('Now toggle back on.'); - await retry.try(async () => { - await PageObjects.upgradeAssistant.toggleDeprecationLogging(); - log.debug('expect state to be ON after toggle'); - expect(await PageObjects.upgradeAssistant.isDeprecationLoggingEnabled()).to.be(true); - expect(await PageObjects.upgradeAssistant.deprecationLoggingEnabledLabel()).to.be('On'); + await retry.waitFor('Elasticsearch deprecations table to be visible', async () => { + return testSubjects.exists('esDeprecationsTable'); }); }); - it.skip('allows user to open cluster tab', async () => { + it('renders the Kibana deprecations page', async () => { await PageObjects.upgradeAssistant.navigateToPage(); - await PageObjects.upgradeAssistant.clickTab('cluster'); - expect(await PageObjects.upgradeAssistant.issueSummaryText()).to.be( - 'You have no cluster issues.' - ); - }); + await PageObjects.upgradeAssistant.clickKibanaDeprecationsPanel(); - it.skip('allows user to open indices tab', async () => { - await PageObjects.upgradeAssistant.navigateToPage(); - await PageObjects.upgradeAssistant.clickTab('indices'); - expect(await PageObjects.upgradeAssistant.issueSummaryText()).to.be( - 'You have no index issues.' - ); + await retry.waitFor('Kibana deprecations table to be visible', async () => { + return testSubjects.exists('kibanaDeprecationsContent'); + }); }); }); } diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 2abd91fd0433a..0b202d3eb1b54 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -438,7 +438,13 @@ export default async function ({ readConfigFile }) { // using this role even for remote clusters global_ccr_role: { elasticsearch: { - cluster: ['manage', 'manage_ccr'], + cluster: ['manage'], + indices: [ + { + names: ['*'], + privileges: ['view_index_metadata'], + }, + ], }, kibana: [ { diff --git a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts index 211bcbbd59219..32332620ffc59 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts +++ b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts @@ -11,7 +11,6 @@ export class UpgradeAssistantPageObject extends FtrService { private readonly retry = this.ctx.getService('retry'); private readonly log = this.ctx.getService('log'); private readonly browser = this.ctx.getService('browser'); - private readonly find = this.ctx.getService('find'); private readonly testSubjects = this.ctx.getService('testSubjects'); private readonly common = this.ctx.getPageObject('common'); @@ -30,47 +29,15 @@ export class UpgradeAssistantPageObject extends FtrService { }); } - async toggleDeprecationLogging() { - this.log.debug('toggleDeprecationLogging()'); - await this.testSubjects.click('upgradeAssistantDeprecationToggle'); - } - - async isDeprecationLoggingEnabled() { - const isDeprecationEnabled = await this.testSubjects.getAttribute( - 'upgradeAssistantDeprecationToggle', - 'aria-checked' - ); - this.log.debug(`Deprecation enabled == ${isDeprecationEnabled}`); - return isDeprecationEnabled === 'true'; - } - - async deprecationLoggingEnabledLabel() { - const loggingEnabledLabel = await this.find.byCssSelector( - '[data-test-subj="upgradeAssistantDeprecationToggle"] ~ span' - ); - return await loggingEnabledLabel.getVisibleText(); - } - - async clickTab(tabId: string) { + async clickEsDeprecationsPanel() { return await this.retry.try(async () => { - this.log.debug('clickTab()'); - await this.find.clickByCssSelector(`.euiTabs .euiTab#${tabId}`); + await this.testSubjects.click('esStatsPanel'); }); } - async waitForTelemetryHidden() { - const self = this; - await this.retry.waitFor('Telemetry to disappear.', async () => { - return (await self.isTelemetryExists()) === false; + async clickKibanaDeprecationsPanel() { + return await this.retry.try(async () => { + await this.testSubjects.click('kibanaStatsPanel'); }); } - - async issueSummaryText() { - this.log.debug('expectIssueSummary()'); - return await this.testSubjects.getVisibleText('upgradeAssistantIssueSummary'); - } - - async isTelemetryExists() { - return await this.testSubjects.exists('upgradeAssistantTelemetryRunning'); - } } From cc21dbd8c07ef4d093233652ecfac544318353f3 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 1 Sep 2021 13:04:18 -0400 Subject: [PATCH 14/93] [Upgrade Assistant] Remove version from UA nav title (#110739) --- x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - x-pack/plugins/upgrade_assistant/public/plugin.ts | 7 +++---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b3e77a39ef6b0..c1205265bd10d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25163,7 +25163,6 @@ "xpack.uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesHelpLinkText": "ヘルプ", "xpack.uiActionsEnhanced.drilldowns.urlDrilldownValidation.urlFormatErrorMessage": "無効な形式:{message}", "xpack.uiActionsEnhanced.drilldowns.urlDrilldownValidation.urlFormatGeneralErrorMessage": "無効なフォーマット。例:{exampleUrl}", - "xpack.upgradeAssistant.appTitle": "{version} アップグレードアシスタント", "xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel": "Elasticsearchの廃止予定", "xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel": "Kibanaの廃止予定", "xpack.upgradeAssistant.breadcrumb.overviewLabel": "アップグレードアシスタント", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index dc43b75b5d1e3..a14bc9542ca0d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25592,7 +25592,6 @@ "xpack.uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesHelpLinkText": "帮助", "xpack.uiActionsEnhanced.drilldowns.urlDrilldownValidation.urlFormatErrorMessage": "格式无效:{message}", "xpack.uiActionsEnhanced.drilldowns.urlDrilldownValidation.urlFormatGeneralErrorMessage": "格式无效。例如:{exampleUrl}", - "xpack.upgradeAssistant.appTitle": "{version} 升级助手", "xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel": "Elasticsearch 弃用", "xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel": "Kibana 弃用", "xpack.upgradeAssistant.breadcrumb.overviewLabel": "升级助手", diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index 03e5c91c99daa..2385bbe8b33fb 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -34,10 +34,9 @@ export class UpgradeAssistantUIPlugin nextMajor: kibanaVersion.major + 1, }; - const pluginName = i18n.translate('xpack.upgradeAssistant.appTitle', { - defaultMessage: '{version} Upgrade Assistant', - values: { version: `${kibanaVersionInfo.nextMajor}.0` }, - }); + const pluginName = i18n.translate('xpack.upgradeAssistant.appTitle', { + defaultMessage: 'Upgrade Assistant', + }); appRegistrar.registerApp({ id: 'upgrade_assistant', From 4430cced134ada3bda4d34cee42f29bc9c9777dc Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 2 Sep 2021 19:57:32 -0400 Subject: [PATCH 15/93] [Upgrade Assistant] New Kibana deprecations page (#110101) --- .../translations/translations/ja-JP.json | 36 +-- .../translations/translations/zh-CN.json | 37 +-- .../es_deprecations/deprecations_list.test.ts | 2 +- .../deprecation_details_flyout.test.ts | 132 ++++++++ .../deprecations_list.test.ts | 125 ++++++++ .../error_handling.test.ts | 80 +++++ .../kibana_deprecations.helpers.ts | 91 +++++- .../kibana_deprecations.test.ts | 245 --------------- .../kibana_deprecations/mocked_responses.ts | 34 ++ .../public/application/app.tsx | 12 +- .../application/components/constants.tsx | 27 +- .../es_deprecations/es_deprecations.tsx | 41 +-- .../es_deprecations/es_deprecations_table.tsx | 6 +- .../deprecation_list_bar => }/index.ts | 5 +- .../_deprecation_details_flyout.scss | 4 + .../deprecation_details_flyout.tsx | 235 ++++++++++++++ .../kibana_deprecations/deprecation_item.tsx | 145 --------- .../kibana_deprecations/deprecation_list.tsx | 150 --------- .../components/kibana_deprecations/index.ts | 2 +- .../kibana_deprecation_errors.tsx | 73 ----- .../kibana_deprecations.tsx | 295 +++++++++++++----- .../kibana_deprecations_table.tsx | 251 +++++++++++++++ .../resolution_table_cell.tsx | 145 +++++++++ .../resolve_deprecation_modal.tsx | 64 ---- .../kibana_deprecations/steps_modal.tsx | 115 ------- .../no_deprecations/no_deprecations.tsx | 9 +- .../components/shared/deprecation_count.tsx | 53 ++++ .../deprecation_list_bar/count_summary.tsx | 41 --- .../deprecation_list_bar.tsx | 69 ---- .../shared/deprecation_pagination.tsx | 24 -- .../application/components/shared/health.tsx | 88 ------ .../application/components/shared/index.ts | 5 +- .../group_by_filter.test.tsx.snap | 24 -- .../__snapshots__/level_filter.test.tsx.snap | 19 -- .../search_bar/group_by_filter.test.tsx | 31 -- .../shared/search_bar/group_by_filter.tsx | 54 ---- .../components/shared/search_bar/index.ts | 8 - .../shared/search_bar/level_filter.test.tsx | 34 -- .../shared/search_bar/level_filter.tsx | 51 --- .../shared/search_bar/search_bar.tsx | 141 --------- .../public/application/components/types.ts | 8 - .../public/application/lib/breadcrumbs.ts | 2 +- .../accessibility/apps/upgrade_assistant.ts | 42 ++- .../upgrade_assistant/upgrade_assistant.ts | 2 +- x-pack/test/functional/config.js | 3 + .../page_objects/upgrade_assistant_page.ts | 17 + 46 files changed, 1434 insertions(+), 1643 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts rename x-pack/plugins/upgrade_assistant/public/application/components/{shared/deprecation_list_bar => }/index.ts (54%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c1205265bd10d..22d8d6d87db87 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25166,16 +25166,6 @@ "xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel": "Elasticsearchの廃止予定", "xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel": "Kibanaの廃止予定", "xpack.upgradeAssistant.breadcrumb.overviewLabel": "アップグレードアシスタント", - "xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "より多く表示させるにはフィルターを変更します。", - "xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "重大", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "インデックス別", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "問題別", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "アップグレード前にこの問題を解決してください。", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel": "重大", - "xpack.upgradeAssistant.checkupTab.deprecations.warningActionTooltip": "アップグレード前にこの問題を解決することをお勧めしますが、必須ではありません。", - "xpack.upgradeAssistant.checkupTab.deprecations.warningLabel": "警告", - "xpack.upgradeAssistant.checkupTab.noDeprecationsLabel": "説明がありません", - "xpack.upgradeAssistant.checkupTab.numDeprecationsShownLabel": "{total} 件中 {numShown} 件を表示中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.cancelButtonLabel": "キャンセル", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.closeButtonLabel": "閉じる", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.continueButtonLabel": "再インデックスを続ける", @@ -25212,16 +25202,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutDetail": "続行する前に、インデックスをバックアップしてください。再インデックスを続行するには、各変更を承諾してください。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutTitle": "このインデックスには元に戻すことのできない破壊的な変更が含まれています", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.documentationLinkLabel": "ドキュメント", - "xpack.upgradeAssistant.deprecationGroupItem.docLinkText": "ドキュメンテーションを表示", - "xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel": "修正する手順を表示", - "xpack.upgradeAssistant.deprecationGroupItem.resolveButtonLabel": "クイック解決", - "xpack.upgradeAssistant.deprecationGroupItemTitle": "'{domainId}'は廃止予定の機能を使用しています", - "xpack.upgradeAssistant.deprecationListBar.collapseAllButtonLabel": "すべて縮小", - "xpack.upgradeAssistant.deprecationListBar.expandAllButtonLabel": "すべて拡張", - "xpack.upgradeAssistant.deprecationListSearchBar.filterErrorMessageLabel": "フィルター無効:{searchTermError}", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderAriaLabel": "フィルター", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderLabel": "フィルター", - "xpack.upgradeAssistant.deprecationListSearchBar.reloadButtonLabel": "再読み込み", "xpack.upgradeAssistant.emptyPrompt.learnMoreDescription": "{nextMajor}への移行に関する詳細をご覧ください。", "xpack.upgradeAssistant.emptyPrompt.title": "{uaVersion} アップグレードアシスタント", "xpack.upgradeAssistant.emptyPrompt.upgradeAssistantDescription": "アップグレードアシスタントはクラスターの廃止予定の設定を特定し、アップグレード前に問題を解決できるようにします。Elastic {nextMajor}にアップグレードするときにここに戻って確認してください。", @@ -25245,25 +25225,11 @@ "xpack.upgradeAssistant.esDeprecationStats.loadingText": "Elasticsearchの廃止統計情報を読み込んでいます...", "xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText": "警告なし。準備ができました。", "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.warningDeprecationsTitle": "警告", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorDescription": "エラーについては、Kibanaサーバーログを確認してください。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorTitle": "Kibana廃止予定を取得できませんでした", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorDescription": "エラーについては、Kibanaサーバーログを確認してください。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorTitle": "一部のKibana廃止予定が正常に取得されませんでした", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "ドキュメント", - "xpack.upgradeAssistant.kibanaDeprecations.errorMessage": "廃止予定の解決エラー", "xpack.upgradeAssistant.kibanaDeprecations.loadingText": "廃止予定を読み込んでいます...", - "xpack.upgradeAssistant.kibanaDeprecations.pageDescription": "アップグレード前に、ここで一覧の問題を確認し、必要な変更を行ってください。アップグレード前に、重大な問題を解決する必要があります。", "xpack.upgradeAssistant.kibanaDeprecations.pageTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.cancelButtonLabel": "キャンセル", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle": "'{domainId}'で廃止予定を解決しますか?", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.resolveButtonLabel": "解決", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.closeButtonLabel": "閉じる", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel": "ドキュメンテーションを表示", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle": "'{domainId}'で廃止予定を解決", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.stepTitle": "ステップ{step}", - "xpack.upgradeAssistant.kibanaDeprecations.successMessage": "廃止予定が解決されました", + "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibanaには{criticalDeprecations}個の重大な廃止予定があります", "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "重大", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "Kibana廃止予定の取得中にエラーが発生しました。", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingText": "Kibana廃止予定統計情報を読み込んでいます…", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a14bc9542ca0d..41d986ef72400 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25595,16 +25595,6 @@ "xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel": "Elasticsearch 弃用", "xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel": "Kibana 弃用", "xpack.upgradeAssistant.breadcrumb.overviewLabel": "升级助手", - "xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "更改筛选以显示更多内容。", - "xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "紧急", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "按索引", - "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "按问题", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "请解决此问题后再升级。", - "xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel": "紧急", - "xpack.upgradeAssistant.checkupTab.deprecations.warningActionTooltip": "建议在升级之前先解决此问题,但这不是必需的。", - "xpack.upgradeAssistant.checkupTab.deprecations.warningLabel": "警告", - "xpack.upgradeAssistant.checkupTab.noDeprecationsLabel": "无弃用内容", - "xpack.upgradeAssistant.checkupTab.numDeprecationsShownLabel": "显示 {numShown} 个,共 {total} 个", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.cancelButtonLabel": "取消", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.closeButtonLabel": "关闭", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.continueButtonLabel": "继续重新索引", @@ -25641,16 +25631,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutDetail": "继续前备份索引。要继续重新索引,请接受每个更改。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.destructiveCallout.calloutTitle": "此索引需要无法恢复的破坏性更改", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.documentationLinkLabel": "文档", - "xpack.upgradeAssistant.deprecationGroupItem.docLinkText": "查看文档", - "xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel": "显示修复步骤", - "xpack.upgradeAssistant.deprecationGroupItem.resolveButtonLabel": "快速解决", - "xpack.upgradeAssistant.deprecationGroupItemTitle": "“{domainId}”正在使用弃用的功能", - "xpack.upgradeAssistant.deprecationListBar.collapseAllButtonLabel": "折叠全部", - "xpack.upgradeAssistant.deprecationListBar.expandAllButtonLabel": "展开全部", - "xpack.upgradeAssistant.deprecationListSearchBar.filterErrorMessageLabel": "筛选无效:{searchTermError}", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderAriaLabel": "筛选", - "xpack.upgradeAssistant.deprecationListSearchBar.placeholderLabel": "筛选", - "xpack.upgradeAssistant.deprecationListSearchBar.reloadButtonLabel": "重新加载", "xpack.upgradeAssistant.emptyPrompt.learnMoreDescription": "详细了解如何迁移到 {nextMajor}。", "xpack.upgradeAssistant.emptyPrompt.title": "{uaVersion} 升级助手", "xpack.upgradeAssistant.emptyPrompt.upgradeAssistantDescription": "升级助手识别集群中弃用的设置,帮助您在升级前解决问题。需要升级到 Elastic {nextMajor} 时,回到这里查看。", @@ -25674,26 +25654,11 @@ "xpack.upgradeAssistant.esDeprecationStats.loadingText": "正在加载 Elasticsearch 弃用统计……", "xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText": "无警告。已就绪!", "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.warningDeprecationsTitle": "警告", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorDescription": "请在 Kibana 服务器日志中查看错误。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorTitle": "无法检索 Kibana 弃用", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorDescription": "请在 Kibana 服务器日志中查看错误。", - "xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorTitle": "未成功检索全部的 Kibana 弃用", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "文档", - "xpack.upgradeAssistant.kibanaDeprecations.errorMessage": "解决弃用时出错", "xpack.upgradeAssistant.kibanaDeprecations.loadingText": "正在加载弃用……", - "xpack.upgradeAssistant.kibanaDeprecations.pageDescription": "在升级之前查看此处所列的问题并进行必要的更改。在升级之前必须解决紧急问题。", "xpack.upgradeAssistant.kibanaDeprecations.pageTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.cancelButtonLabel": "取消", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle": "在“{domainId}”中解决弃用?", - "xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.resolveButtonLabel": "解决", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.closeButtonLabel": "关闭", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel": "查看文档", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle": "在“{domainId}”中解决弃用", - "xpack.upgradeAssistant.kibanaDeprecations.stepsModal.stepTitle": "步骤 {step}", - "xpack.upgradeAssistant.kibanaDeprecations.successMessage": "弃用已解决", - "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibana 有 {criticalDeprecations} 个紧急{criticalDeprecations, plural, other {弃用}}", + "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibana 具有 {criticalDeprecations} 个关键弃用", "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "紧急", "xpack.upgradeAssistant.kibanaDeprecationStats.getWarningDeprecationsMessage": "Kibana 有 {warningDeprecations} 个警告{warningDeprecations, plural, other {弃用}}", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "检索 Kibana 弃用时发生错误。", diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index ffee297f6f574..316e1a65f0890 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -18,7 +18,7 @@ import { createEsDeprecationsMockResponse, } from './mocked_responses'; -describe('Deprecations table', () => { +describe('ES deprecations table', () => { let testBed: ElasticsearchTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts new file mode 100644 index 0000000000000..c65f15fda2e3c --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts @@ -0,0 +1,132 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { setupEnvironment } from '../helpers'; +import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { kibanaDeprecationsMockResponse } from './mocked_responses'; + +describe('Kibana deprecation details flyout', () => { + let testBed: KibanaTestBed; + const { server } = setupEnvironment(); + const deprecationService = deprecationsServiceMock.createStartContract(); + + afterAll(() => { + server.restore(); + }); + + beforeEach(async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest + .fn() + .mockReturnValue(kibanaDeprecationsMockResponse); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + testBed.component.update(); + }); + + describe('Deprecation with manual steps', () => { + test('renders flyout with manual steps only', async () => { + const { find, exists, actions } = testBed; + const manualDeprecation = kibanaDeprecationsMockResponse[1]; + + await actions.table.clickDeprecationAt(1); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe(manualDeprecation.title); + expect(find('manualStepsList').find('li').length).toEqual( + manualDeprecation.correctiveActions.manualSteps.length + ); + + // Quick resolve callout and button should not display + expect(exists('quickResolveCallout')).toBe(false); + expect(exists('resolveButton')).toBe(false); + }); + }); + + describe('Deprecation with automatic resolution', () => { + test('resolves deprecation successfully', async () => { + const { find, exists, actions } = testBed; + const quickResolveDeprecation = kibanaDeprecationsMockResponse[0]; + + await actions.table.clickDeprecationAt(0); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe( + quickResolveDeprecation.title + ); + expect(find('manualStepsList').find('li').length).toEqual( + quickResolveDeprecation.correctiveActions.manualSteps.length + ); + + // Quick resolve callout and button should display + expect(exists('quickResolveCallout')).toBe(true); + expect(exists('resolveButton')).toBe(true); + + await actions.flyout.clickResolveButton(); + + // Flyout should close after button click + expect(exists('kibanaDeprecationDetails')).toBe(false); + + // Reopen the flyout + await actions.table.clickDeprecationAt(0); + + // Resolve information should not display and Quick resolve button should be disabled + expect(exists('resolveSection')).toBe(false); + expect(find('resolveButton').props().disabled).toBe(true); + expect(find('resolveButton').text()).toContain('Resolved'); + }); + + test('handles resolve failure', async () => { + const { find, exists, actions } = testBed; + const quickResolveDeprecation = kibanaDeprecationsMockResponse[0]; + + deprecationService.resolveDeprecation.mockReturnValue( + Promise.resolve({ + status: 'fail', + reason: 'resolve failed', + }) + ); + + await actions.table.clickDeprecationAt(0); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe( + quickResolveDeprecation.title + ); + + // Quick resolve callout and button should display + expect(exists('quickResolveCallout')).toBe(true); + expect(exists('resolveButton')).toBe(true); + + await actions.flyout.clickResolveButton(); + + // Flyout should close after button click + expect(exists('kibanaDeprecationDetails')).toBe(false); + + // Reopen the flyout + await actions.table.clickDeprecationAt(0); + + // Verify error displays + expect(exists('quickResolveError')).toBe(true); + // Resolve information should display and Quick resolve button should be enabled + expect(exists('resolveSection')).toBe(true); + expect(find('resolveButton').props().disabled).toBe(false); + expect(find('resolveButton').text()).toContain('Try again'); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts new file mode 100644 index 0000000000000..c3e3581409947 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts @@ -0,0 +1,125 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { setupEnvironment } from '../helpers'; +import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { kibanaDeprecationsMockResponse } from './mocked_responses'; + +const criticalDeprecations = kibanaDeprecationsMockResponse.filter( + (deprecation) => deprecation.level === 'critical' +); +const warningDeprecations = kibanaDeprecationsMockResponse.filter( + (deprecation) => deprecation.level === 'warning' +); +const configDeprecations = kibanaDeprecationsMockResponse.filter( + (deprecation) => deprecation.deprecationType === 'config' +); + +describe('Kibana deprecations table', () => { + let testBed: KibanaTestBed; + const { server } = setupEnvironment(); + const deprecationService = deprecationsServiceMock.createStartContract(); + + afterAll(() => { + server.restore(); + }); + + beforeEach(async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest + .fn() + .mockReturnValue(kibanaDeprecationsMockResponse); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + testBed.component.update(); + }); + + test('renders deprecations', () => { + const { exists, table } = testBed; + + expect(exists('kibanaDeprecations')).toBe(true); + + const { tableCellsValues } = table.getMetaData('kibanaDeprecationsTable'); + + expect(tableCellsValues.length).toEqual(kibanaDeprecationsMockResponse.length); + }); + + it('refreshes deprecation data', async () => { + const { actions } = testBed; + + expect(deprecationService.getAllDeprecations).toHaveBeenCalledTimes(1); + + await actions.table.clickRefreshButton(); + + expect(deprecationService.getAllDeprecations).toHaveBeenCalledTimes(2); + }); + + it('shows critical and warning deprecations count', () => { + const { find } = testBed; + + expect(find('criticalDeprecationsCount').text()).toContain(criticalDeprecations.length); + expect(find('warningDeprecationsCount').text()).toContain(warningDeprecations.length); + }); + + describe('Search bar', () => { + it('filters by "critical" status', async () => { + const { actions, table } = testBed; + + // Show only critical deprecations + await actions.searchBar.clickCriticalFilterButton(); + const { rows: criticalRows } = table.getMetaData('kibanaDeprecationsTable'); + expect(criticalRows.length).toEqual(criticalDeprecations.length); + + // Show all deprecations + await actions.searchBar.clickCriticalFilterButton(); + const { rows: allRows } = table.getMetaData('kibanaDeprecationsTable'); + expect(allRows.length).toEqual(kibanaDeprecationsMockResponse.length); + }); + + it('filters by type', async () => { + const { table, actions } = testBed; + + await actions.searchBar.openTypeFilterDropdown(); + await actions.searchBar.filterByConfigType(); + + const { rows: configRows } = table.getMetaData('kibanaDeprecationsTable'); + + expect(configRows.length).toEqual(configDeprecations.length); + }); + }); + + describe('No deprecations', () => { + beforeEach(async () => { + await act(async () => { + testBed = await setupKibanaPage({ isReadOnlyMode: false }); + }); + + const { component } = testBed; + + component.update(); + }); + + test('renders prompt', () => { + const { exists, find } = testBed; + expect(exists('noDeprecationsPrompt')).toBe(true); + expect(find('noDeprecationsPrompt').text()).toContain( + 'Your Kibana configuration is up to date' + ); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts new file mode 100644 index 0000000000000..6de1fd339f3cc --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts @@ -0,0 +1,80 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { setupEnvironment } from '../helpers'; +import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { kibanaDeprecationsMockResponse } from './mocked_responses'; + +describe('Error handling', () => { + let testBed: KibanaTestBed; + const { server } = setupEnvironment(); + const deprecationService = deprecationsServiceMock.createStartContract(); + + afterAll(() => { + server.restore(); + }); + + test('handles plugin error', async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest.fn().mockReturnValue([ + ...kibanaDeprecationsMockResponse, + { + domainId: 'failed_plugin_id', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: `Failed to get deprecations info for plugin "failed_plugin_id".`, + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + ]); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { component, exists, find } = testBed; + + component.update(); + + expect(exists('kibanaDeprecationErrors')).toBe(true); + expect(find('kibanaDeprecationErrors').text()).toContain( + 'Deprecation warnings may be incomplete' + ); + }); + + test('handles request error', async () => { + await act(async () => { + deprecationService.getAllDeprecations = jest + .fn() + .mockRejectedValue(new Error('Internal Server Error')); + + testBed = await setupKibanaPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { component, exists, find } = testBed; + + component.update(); + + expect(exists('kibanaRequestError')).toBe(true); + expect(find('kibanaRequestError').text()).toContain('Could not retrieve Kibana deprecations'); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts index 860c9249b266a..345a06d3d80a0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.helpers.ts @@ -4,9 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; -import { KibanaDeprecationsContent } from '../../../public/application/components/kibana_deprecations'; +import { act } from 'react-dom/test-utils'; +import { registerTestBed, TestBed, TestBedConfig, findTestSubject } from '@kbn/test/jest'; +import { KibanaDeprecations } from '../../../public/application/components'; import { WithAppDependencies } from '../helpers'; const testBedConfig: TestBedConfig = { @@ -22,17 +22,92 @@ export type KibanaTestBed = TestBed & { }; const createActions = (testBed: TestBed) => { + const { component, find, table } = testBed; + /** * User Actions */ + const tableActions = { + clickRefreshButton: async () => { + await act(async () => { + find('refreshButton').simulate('click'); + }); + + component.update(); + }, + + clickDeprecationAt: async (index: number) => { + const { rows } = table.getMetaData('kibanaDeprecationsTable'); + + const deprecationDetailsLink = findTestSubject( + rows[index].reactWrapper, + 'deprecationDetailsLink' + ); + + await act(async () => { + deprecationDetailsLink.simulate('click'); + }); + component.update(); + }, + }; + + const searchBarActions = { + openTypeFilterDropdown: async () => { + await act(async () => { + // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector + find('kibanaDeprecations') + .find('.euiSearchBar__filtersHolder') + .find('.euiPopover') + .find('.euiFilterButton') + .at(0) + .simulate('click'); + }); + + component.update(); + }, + + clickCriticalFilterButton: async () => { + await act(async () => { + // EUI doesn't support data-test-subj's on the filter buttons, so we must access via CSS selector + find('kibanaDeprecations') + .find('.euiSearchBar__filtersHolder') + .find('.euiFilterButton') + .at(0) + .simulate('click'); + }); + + component.update(); + }, + + filterByConfigType: async () => { + // We need to read the document "body" as the filter dropdown options are added there and not inside + // the component DOM tree. The "Config" option is expected to be the first item. + const configTypeFilterButton: HTMLButtonElement | null = document.body.querySelector( + '.euiFilterSelect__items .euiFilterSelectItem' + ); + + await act(async () => { + configTypeFilterButton!.click(); + }); + + component.update(); + }, + }; + + const flyoutActions = { + clickResolveButton: async () => { + await act(async () => { + find('resolveButton').simulate('click'); + }); - const clickExpandAll = () => { - const { find } = testBed; - find('expandAll').simulate('click'); + component.update(); + }, }; return { - clickExpandAll, + table: tableActions, + flyout: flyoutActions, + searchBar: searchBarActions, }; }; @@ -40,7 +115,7 @@ export const setupKibanaPage = async ( overrides?: Record ): Promise => { const initTestBed = registerTestBed( - WithAppDependencies(KibanaDeprecationsContent, overrides), + WithAppDependencies(KibanaDeprecations, overrides), testBedConfig ); const testBed = await initTestBed(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts deleted file mode 100644 index 7ac2b28ada5e0..0000000000000 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/kibana_deprecations.test.ts +++ /dev/null @@ -1,245 +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 type { DomainDeprecationDetails } from 'kibana/public'; -import { act } from 'react-dom/test-utils'; -import { deprecationsServiceMock } from 'src/core/public/mocks'; - -import { setupEnvironment } from '../helpers'; -import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; - -describe('Kibana deprecations', () => { - let testBed: KibanaTestBed; - const { server } = setupEnvironment(); - - afterAll(() => { - server.restore(); - }); - - describe('With deprecations', () => { - const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ - { - title: 'mock-deprecation-title', - correctiveActions: { - manualSteps: ['Step 1', 'Step 2', 'Step 3'], - api: { - method: 'POST', - path: '/test', - }, - }, - domainId: 'test_domain', - level: 'critical', - message: 'Test deprecation message', - }, - ]; - - beforeEach(async () => { - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockReturnValue(kibanaDeprecationsMockResponse); - - testBed = await setupKibanaPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - testBed.component.update(); - }); - - test('renders deprecations', () => { - const { exists, find } = testBed; - expect(exists('kibanaDeprecationsContent')).toBe(true); - expect(find('kibanaDeprecationItem').length).toEqual(1); - }); - - describe('manual steps modal', () => { - test('renders modal with a list of steps to fix a deprecation', async () => { - const { component, actions, exists, find } = testBed; - const deprecation = kibanaDeprecationsMockResponse[0]; - - expect(exists('kibanaDeprecationsContent')).toBe(true); - - // Open all deprecations - actions.clickExpandAll(); - - const accordionTestSubj = `${deprecation.domainId}Deprecation`; - - await act(async () => { - find(`${accordionTestSubj}.stepsButton`).simulate('click'); - }); - - component.update(); - - // We need to read the document "body" as the modal is added there and not inside - // the component DOM tree. - let modal = document.body.querySelector('[data-test-subj="stepsModal"]'); - - expect(modal).not.toBeNull(); - expect(modal!.textContent).toContain(`Resolve deprecation in '${deprecation.domainId}'`); - - const steps: NodeListOf | null = modal!.querySelectorAll( - '[data-test-subj="fixDeprecationSteps"] .euiStep' - ); - - expect(steps).not.toBe(null); - expect(steps.length).toEqual(deprecation!.correctiveActions!.manualSteps!.length); - - await act(async () => { - const closeButton: HTMLButtonElement | null = modal!.querySelector( - '[data-test-subj="closeButton"]' - ); - - closeButton!.click(); - }); - - component.update(); - - // Confirm modal closed and no longer appears in the DOM - modal = document.body.querySelector('[data-test-subj="stepsModal"]'); - expect(modal).toBe(null); - }); - }); - - describe('resolve modal', () => { - test('renders confirmation modal to resolve a deprecation', async () => { - const { component, actions, exists, find } = testBed; - const deprecation = kibanaDeprecationsMockResponse[0]; - - expect(exists('kibanaDeprecationsContent')).toBe(true); - - // Open all deprecations - actions.clickExpandAll(); - - const accordionTestSubj = `${deprecation.domainId}Deprecation`; - - await act(async () => { - find(`${accordionTestSubj}.resolveButton`).simulate('click'); - }); - - component.update(); - - // We need to read the document "body" as the modal is added there and not inside - // the component DOM tree. - let modal = document.body.querySelector('[data-test-subj="resolveModal"]'); - - expect(modal).not.toBe(null); - expect(modal!.textContent).toContain(`Resolve deprecation in '${deprecation.domainId}'`); - - const confirmButton: HTMLButtonElement | null = modal!.querySelector( - '[data-test-subj="confirmModalConfirmButton"]' - ); - - await act(async () => { - confirmButton!.click(); - }); - - component.update(); - - // Confirm modal should close and no longer appears in the DOM - modal = document.body.querySelector('[data-test-subj="resolveModal"]'); - expect(modal).toBe(null); - }); - }); - }); - - describe('No deprecations', () => { - beforeEach(async () => { - await act(async () => { - testBed = await setupKibanaPage({ isReadOnlyMode: false }); - }); - - const { component } = testBed; - - component.update(); - }); - - test('renders prompt', () => { - const { exists, find } = testBed; - expect(exists('noDeprecationsPrompt')).toBe(true); - expect(find('noDeprecationsPrompt').text()).toContain( - 'Your Kibana configuration is up to date' - ); - }); - }); - - describe('Error handling', () => { - test('handles request error', async () => { - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockRejectedValue(new Error('Internal Server Error')); - - testBed = await setupKibanaPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - const { component, exists, find } = testBed; - - component.update(); - - expect(exists('kibanaRequestError')).toBe(true); - expect(find('kibanaRequestError').text()).toContain('Could not retrieve Kibana deprecations'); - }); - - test('handles deprecation service error', async () => { - const domainId = 'test'; - const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ - { - domainId, - title: `Failed to fetch deprecations for ${domainId}`, - message: `Failed to get deprecations info for plugin "${domainId}".`, - level: 'fetch_error', - correctiveActions: { - manualSteps: ['Check Kibana server logs for error message.'], - }, - }, - ]; - - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockReturnValue(kibanaDeprecationsMockResponse); - - testBed = await setupKibanaPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - const { component, exists, find, actions } = testBed; - component.update(); - - // Verify top-level callout renders - expect(exists('kibanaPluginError')).toBe(true); - expect(find('kibanaPluginError').text()).toContain( - 'Not all Kibana deprecations were retrieved successfully' - ); - - // Open all deprecations - actions.clickExpandAll(); - - // Verify callout also displays for deprecation with error - expect(exists(`${domainId}Error`)).toBe(true); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts new file mode 100644 index 0000000000000..261fe719bf5bf --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { DomainDeprecationDetails } from 'kibana/public'; + +export const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ + { + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + api: { + method: 'POST', + path: '/test', + }, + }, + domainId: 'test_domain_1', + level: 'critical', + title: 'Test deprecation title 1', + message: 'Test deprecation message 1', + deprecationType: 'config', + }, + { + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + }, + domainId: 'test_domain_2', + level: 'warning', + title: 'Test deprecation title 1', + message: 'Test deprecation message 2', + deprecationType: 'feature', + }, +]; diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index cc921bdaefc15..0d32d1b661b84 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -8,16 +8,12 @@ import React from 'react'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; import { ScopedHistory } from 'src/core/public'; -import { GlobalFlyout } from '../shared_imports'; -import { APP_WRAPPER_CLASS } from '../shared_imports'; -import { AppContextProvider, useAppContext } from './app_context'; -import { ComingSoonPrompt } from './components/coming_soon_prompt'; -import { EsDeprecations } from './components/es_deprecations'; -import { KibanaDeprecationsContent } from './components/kibana_deprecations'; -import { Overview } from './components/overview'; import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; +import { APP_WRAPPER_CLASS, GlobalFlyout } from '../shared_imports'; import { AppDependencies } from '../types'; +import { AppContextProvider, useAppContext } from './app_context'; +import { EsDeprecations, ComingSoonPrompt, KibanaDeprecations, Overview } from './components'; const { GlobalFlyoutProvider } = GlobalFlyout; @@ -33,7 +29,7 @@ const App: React.FunctionComponent = () => { - + ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx index c7f974fab6a89..34850e6c97543 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx @@ -5,30 +5,8 @@ * 2.0. */ -import { IconColor } from '@elastic/eui'; -import { invert } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { DeprecationInfo } from '../../../common/types'; - -export const LEVEL_MAP: { [level: string]: number } = { - warning: 0, - critical: 1, -}; - -interface ReverseLevelMap { - [idx: number]: DeprecationInfo['level']; -} - -export const REVERSE_LEVEL_MAP: ReverseLevelMap = invert(LEVEL_MAP) as ReverseLevelMap; - -export const COLOR_MAP: { [level: string]: IconColor } = { - warning: 'default', - critical: 'danger', -}; - -export const DEPRECATIONS_PER_PAGE = 25; - export const DEPRECATION_TYPE_MAP = { cluster_settings: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.clusterDeprecationTypeLabel', @@ -49,3 +27,8 @@ export const DEPRECATION_TYPE_MAP = { defaultMessage: 'Machine Learning', }), }; + +export const PAGINATION_CONFIG = { + initialPageSize: 50, + pageSizeOptions: [50, 100, 200], +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 52722a52be6d3..b823740433f84 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -8,14 +8,7 @@ import React, { useEffect, useMemo } from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { - EuiPageHeader, - EuiSpacer, - EuiPageContent, - EuiFlexGroup, - EuiFlexItem, - EuiHealth, -} from '@elastic/eui'; +import { EuiPageHeader, EuiSpacer, EuiPageContent } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { EnrichedDeprecationInfo } from '../../../../common/types'; @@ -23,7 +16,7 @@ import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { EsDeprecationsTable } from './es_deprecations_table'; import { EsDeprecationErrors } from './es_deprecation_errors'; -import { NoDeprecationsPrompt } from '../shared'; +import { NoDeprecationsPrompt, DeprecationCount } from '../shared'; const getDeprecationCountByLevel = (deprecations: EnrichedDeprecationInfo[]) => { const criticalDeprecations: EnrichedDeprecationInfo[] = []; @@ -54,20 +47,6 @@ const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { defaultMessage: 'Loading deprecations…', }), - getCriticalStatusLabel: (count: number) => - i18n.translate('xpack.upgradeAssistant.esDeprecations.criticalStatusLabel', { - defaultMessage: 'Critical: {count}', - values: { - count, - }, - }), - getWarningStatusLabel: (count: number) => - i18n.translate('xpack.upgradeAssistant.esDeprecations.warningStatusLabel', { - defaultMessage: 'Warning: {count}', - values: { - count, - }, - }), }; export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { @@ -132,18 +111,10 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { return (
- - - - {i18nTexts.getCriticalStatusLabel(deprecationsCountByLevel.criticalDeprecations)} - - - - - {i18nTexts.getWarningStatusLabel(deprecationsCountByLevel.warningDeprecations)} - - - + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx index 30866e9299f34..f1b693fa48f57 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx @@ -33,7 +33,7 @@ import { ReindexTableRow, } from './deprecation_types'; import { DeprecationTableColumns } from '../types'; -import { DEPRECATION_TYPE_MAP } from '../constants'; +import { DEPRECATION_TYPE_MAP, PAGINATION_CONFIG } from '../constants'; const i18nTexts = { refreshButtonLabel: i18n.translate( @@ -99,7 +99,7 @@ const cellToLabelMap = { }; const cellTypes = Object.keys(cellToLabelMap) as DeprecationTableColumns[]; -const pageSizeOptions = [50, 100, 200]; +const pageSizeOptions = PAGINATION_CONFIG.pageSizeOptions; const renderTableRowCells = (deprecation: EnrichedDeprecationInfo) => { switch (deprecation.correctiveAction?.type) { @@ -151,7 +151,7 @@ export const EsDeprecationsTable: React.FunctionComponent = ({ sortField: 'isCritical', }); - const [itemsPerPage, setItemsPerPage] = useState(pageSizeOptions[0]); + const [itemsPerPage, setItemsPerPage] = useState(PAGINATION_CONFIG.initialPageSize); const [currentPageIndex, setCurrentPageIndex] = useState(0); const [searchQuery, setSearchQuery] = useState(EuiSearchBar.Query.MATCH_ALL); const [searchError, setSearchError] = useState<{ message: string } | undefined>(undefined); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/index.ts similarity index 54% rename from x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/index.ts index cbc04fd86bfbd..8924fa2d355a1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/index.ts @@ -5,4 +5,7 @@ * 2.0. */ -export { DeprecationListBar } from './deprecation_list_bar'; +export { KibanaDeprecations } from './kibana_deprecations'; +export { EsDeprecations } from './es_deprecations'; +export { ComingSoonPrompt } from './coming_soon_prompt'; +export { Overview } from './overview'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss new file mode 100644 index 0000000000000..c877ea4b48821 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/_deprecation_details_flyout.scss @@ -0,0 +1,4 @@ +// Used to add spacing between the list of manual deprecation steps +.upgResolveStep { + margin-bottom: $euiSizeL; +} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx new file mode 100644 index 0000000000000..d9d7b50c87f0c --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -0,0 +1,235 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiButtonEmpty, + EuiButton, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiText, + EuiCallOut, + EuiLink, + EuiSpacer, +} from '@elastic/eui'; + +import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; + +import './_deprecation_details_flyout.scss'; + +export interface DeprecationDetailsFlyoutProps { + deprecation: KibanaDeprecationDetails; + closeFlyout: () => void; + resolveDeprecation: (deprecationDetails: KibanaDeprecationDetails) => Promise; + deprecationResolutionState?: DeprecationResolutionState; +} + +const i18nTexts = { + learnMoreLinkLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.learnMoreLinkLabel', + { + defaultMessage: 'Learn more about this deprecation', + } + ), + closeButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.closeButtonLabel', + { + defaultMessage: 'Close', + } + ), + quickResolveButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveButtonLabel', + { + defaultMessage: 'Quick resolve', + } + ), + retryQuickResolveButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.retryQuickResolveButtonLabel', + { + defaultMessage: 'Try again', + } + ), + resolvedButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.resolvedButtonLabel', + { + defaultMessage: 'Resolved', + } + ), + quickResolveInProgressButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveInProgressButtonLabel', + { + defaultMessage: 'Resolution in progress…', + } + ), + quickResolveCalloutTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveCalloutTitle', + { + defaultMessage: 'Quick resolve action available', + } + ), + quickResolveErrorTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveErrorTitle', + { + defaultMessage: 'Error resolving deprecation', + } + ), + quickResolveCalloutDescription: ( + + {i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveText', { + defaultMessage: 'Quick resolve', + })} + + ), + }} + /> + ), + manualFixTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.manualFixTitle', + { + defaultMessage: 'Fix manually', + } + ), +}; + +const getQuickResolveButtonLabel = (deprecationResolutionState?: DeprecationResolutionState) => { + if (deprecationResolutionState?.resolveDeprecationStatus === 'in_progress') { + return i18nTexts.quickResolveInProgressButtonLabel; + } + + if (deprecationResolutionState?.resolveDeprecationStatus === 'ok') { + return i18nTexts.resolvedButtonLabel; + } + + if (deprecationResolutionState?.resolveDeprecationError) { + return i18nTexts.retryQuickResolveButtonLabel; + } + + return i18nTexts.quickResolveButtonLabel; +}; + +export const DeprecationDetailsFlyout = ({ + deprecation, + closeFlyout, + resolveDeprecation, + deprecationResolutionState, +}: DeprecationDetailsFlyoutProps) => { + const { documentationUrl, message, correctiveActions, title } = deprecation; + + return ( + <> + + +

{title}

+
+
+ + {deprecationResolutionState?.resolveDeprecationStatus === 'fail' && ( + <> + + {deprecationResolutionState.resolveDeprecationError} + + + + )} + + +

{message}

+ + {documentationUrl && ( +

+ + {i18nTexts.learnMoreLinkLabel} + +

+ )} +
+ + + + {/* Hide resolution steps if already resolved */} + {deprecationResolutionState?.resolveDeprecationStatus !== 'ok' && ( +
+ {correctiveActions.api && ( + <> + +

{i18nTexts.quickResolveCalloutDescription}

+
+ + + + )} + + +

{i18nTexts.manualFixTitle}

+
+ + + + +
    + {correctiveActions.manualSteps.map((step, stepIndex) => ( +
  1. + {step} +
  2. + ))} +
+
+
+ )} +
+ + + + + + {i18nTexts.closeButtonLabel} + + + + {/* Only show the "Quick resolve" button if deprecation supports it */} + {correctiveActions.api && ( + + resolveDeprecation(deprecation)} + isLoading={Boolean( + deprecationResolutionState?.resolveDeprecationStatus === 'in_progress' + )} + disabled={Boolean(deprecationResolutionState?.resolveDeprecationStatus === 'ok')} + > + {getQuickResolveButtonLabel(deprecationResolutionState)} + + + )} + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx deleted file mode 100644 index 5bcc49590c55e..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React, { FunctionComponent } from 'react'; -import { - EuiAccordion, - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiButtonEmpty, - EuiText, - EuiCallOut, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import type { DomainDeprecationDetails } from 'kibana/public'; -import { DeprecationHealth } from '../shared'; -import { LEVEL_MAP } from '../constants'; -import { StepsModalContent } from './steps_modal'; - -const i18nTexts = { - getDeprecationTitle: (domainId: string) => { - return i18n.translate('xpack.upgradeAssistant.deprecationGroupItemTitle', { - defaultMessage: "'{domainId}' is using a deprecated feature", - values: { - domainId, - }, - }); - }, - docLinkText: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.docLinkText', { - defaultMessage: 'View documentation', - }), - manualFixButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel', - { - defaultMessage: 'Show steps to fix', - } - ), - resolveButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationGroupItem.resolveButtonLabel', - { - defaultMessage: 'Quick resolve', - } - ), -}; - -export interface Props { - deprecation: DomainDeprecationDetails; - index: number; - forceExpand: boolean; - showStepsModal: (modalContent: StepsModalContent) => void; - showResolveModal: (deprecation: DomainDeprecationDetails) => void; -} - -export const KibanaDeprecationAccordion: FunctionComponent = ({ - deprecation, - forceExpand, - index, - showStepsModal, - showResolveModal, -}) => { - const { domainId, level, message, documentationUrl, correctiveActions } = deprecation; - - return ( - } - > - - - - {level === 'fetch_error' ? ( - - ) : ( - <> -

{message}

- - {(documentationUrl || correctiveActions?.manualSteps) && ( - - {correctiveActions?.api && ( - - showResolveModal(deprecation)} - > - {i18nTexts.resolveButtonLabel} - - - )} - - {correctiveActions?.manualSteps && ( - - - showStepsModal({ - domainId, - steps: correctiveActions.manualSteps!, - documentationUrl, - }) - } - > - {i18nTexts.manualFixButtonLabel} - - - )} - - {documentationUrl && ( - - - {i18nTexts.docLinkText} - - - )} - - )} - - )} -
-
-
-
- ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx deleted file mode 100644 index fb61efc373acf..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent, useState, useEffect } from 'react'; -import { groupBy } from 'lodash'; -import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; - -import type { DomainDeprecationDetails } from 'kibana/public'; - -import { LevelFilterOption } from '../types'; -import { SearchBar, DeprecationListBar, DeprecationPagination } from '../shared'; -import { DEPRECATIONS_PER_PAGE } from '../constants'; -import { KibanaDeprecationAccordion } from './deprecation_item'; -import { StepsModalContent } from './steps_modal'; -import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; - -interface Props { - deprecations: DomainDeprecationDetails[]; - showStepsModal: (newStepsModalContent: StepsModalContent) => void; - showResolveModal: (deprecation: DomainDeprecationDetails) => void; - reloadDeprecations: () => Promise; - isLoading: boolean; -} - -const getFilteredDeprecations = ( - deprecations: DomainDeprecationDetails[], - level: LevelFilterOption, - search: string -) => { - return deprecations - .filter((deprecation) => { - return level === 'all' || deprecation.level === level; - }) - .filter((filteredDep) => { - if (search.length > 0) { - try { - // 'i' is used for case-insensitive matching - const searchReg = new RegExp(search, 'i'); - return searchReg.test(filteredDep.message); - } catch (e) { - // ignore any regexp errors - return true; - } - } - return true; - }); -}; - -export const KibanaDeprecationList: FunctionComponent = ({ - deprecations, - showStepsModal, - showResolveModal, - reloadDeprecations, - isLoading, -}) => { - const [currentFilter, setCurrentFilter] = useState('all'); - const [search, setSearch] = useState(''); - const [expandState, setExpandState] = useState({ - forceExpand: false, - expandNumber: 0, - }); - const [currentPage, setCurrentPage] = useState(0); - - const setExpandAll = (expandAll: boolean) => { - setExpandState({ forceExpand: expandAll, expandNumber: expandState.expandNumber + 1 }); - }; - - const levelGroups = groupBy(deprecations, 'level'); - const levelToDeprecationCountMap = Object.keys(levelGroups).reduce((counts, level) => { - counts[level] = levelGroups[level].length; - return counts; - }, {} as { [level: string]: number }); - - const filteredDeprecations = getFilteredDeprecations(deprecations, currentFilter, search); - - const deprecationsWithErrors = deprecations.filter((dep) => dep.level === 'fetch_error'); - - useEffect(() => { - const pageCount = Math.ceil(filteredDeprecations.length / DEPRECATIONS_PER_PAGE); - if (currentPage >= pageCount) { - setCurrentPage(0); - } - }, [filteredDeprecations, currentPage]); - - return ( - <> - - - {deprecationsWithErrors.length > 0 && ( - <> - - - - )} - - - - - - <> - {filteredDeprecations - .slice(currentPage * DEPRECATIONS_PER_PAGE, (currentPage + 1) * DEPRECATIONS_PER_PAGE) - .map((deprecation, index) => [ -
- - -
, - ])} - - {/* Only show pagination if we have more than DEPRECATIONS_PER_PAGE */} - {filteredDeprecations.length > DEPRECATIONS_PER_PAGE && ( - <> - - - - - )} - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts index 84d2b88757188..6a1375f57cd43 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { KibanaDeprecationsContent } from './kibana_deprecations'; +export { KibanaDeprecations } from './kibana_deprecations'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx deleted file mode 100644 index 79ada21941b56..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiPageContent, EuiEmptyPrompt } from '@elastic/eui'; - -interface Props { - errorType: 'pluginError' | 'requestError'; -} - -const i18nTexts = { - pluginError: { - title: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorTitle', { - defaultMessage: 'Not all Kibana deprecations were retrieved successfully', - }), - description: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorDescription', - { - defaultMessage: 'Check the Kibana server logs for errors.', - } - ), - }, - loadingError: { - title: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorTitle', { - defaultMessage: 'Could not retrieve Kibana deprecations', - }), - description: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorDescription', - { - defaultMessage: 'Check the Kibana server logs for errors.', - } - ), - }, -}; - -export const KibanaDeprecationErrors: React.FunctionComponent = ({ errorType }) => { - if (errorType === 'pluginError') { - return ( - - {i18nTexts.pluginError.title}} - body={

{i18nTexts.pluginError.description}

} - /> -
- ); - } - - return ( - - {i18nTexts.loadingError.title}} - body={

{i18nTexts.loadingError.description}

} - /> -
- ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 90f8936d0e38d..a6d7e4fdb674a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -5,30 +5,44 @@ * 2.0. */ -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useState, useCallback, useMemo } from 'react'; +import uuid from 'uuid'; import { withRouter, RouteComponentProps } from 'react-router-dom'; - -import { EuiButtonEmpty, EuiPageContent, EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut, EuiEmptyPrompt } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import type { DomainDeprecationDetails } from 'kibana/public'; -import { SectionLoading } from '../../../shared_imports'; +import { SectionLoading, GlobalFlyout } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; -import { NoDeprecationsPrompt } from '../shared'; -import { KibanaDeprecationList } from './deprecation_list'; -import { StepsModal, StepsModalContent } from './steps_modal'; -import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; -import { ResolveDeprecationModal } from './resolve_deprecation_modal'; -import { LEVEL_MAP } from '../constants'; +import { NoDeprecationsPrompt, DeprecationCount } from '../shared'; +import { KibanaDeprecationsTable } from './kibana_deprecations_table'; +import { + DeprecationDetailsFlyout, + DeprecationDetailsFlyoutProps, +} from './deprecation_details_flyout'; + +const { useGlobalFlyout } = GlobalFlyout; const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { - defaultMessage: 'Kibana', - }), - pageDescription: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageDescription', { - defaultMessage: - 'Review the issues listed here and make the necessary changes before upgrading. Critical issues must be resolved before you upgrade.', + defaultMessage: 'Kibana deprecation warnings', }), + pageDescription: ( + + {i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.quickResolveText', { + defaultMessage: 'Quick Resolve', + })} + + ), + }} + /> + ), docLinkText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.docLinkText', { defaultMessage: 'Documentation', }), @@ -38,47 +52,114 @@ const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.loadingText', { defaultMessage: 'Loading deprecations…', }), - successMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.successMessage', { - defaultMessage: 'Deprecation resolved', - }), - errorMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.errorMessage', { - defaultMessage: 'Error resolving deprecation', + kibanaDeprecationErrorTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.kibanaDeprecationErrorTitle', + { + defaultMessage: 'Deprecation warnings may be incomplete', + } + ), + getKibanaDeprecationErrorDescription: (pluginIds: string[]) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.kibanaDeprecationErrorDescription', { + defaultMessage: + 'Failed to get deprecation warnings for {pluginCount, plural, one {this plugin} other {these plugins}}: {pluginIds}. Check the Kibana server logs for more details.', + values: { + pluginCount: pluginIds.length, + pluginIds: pluginIds.join(', '), + }, + }), + requestErrorTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.requestErrorTitle', { + defaultMessage: 'Could not retrieve Kibana deprecations', }), + requestErrorDescription: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecationErrors.requestErrorDescription', + { + defaultMessage: 'Check the Kibana server logs for errors.', + } + ), }; -const sortByLevelDesc = (a: DomainDeprecationDetails, b: DomainDeprecationDetails) => { - return -1 * (LEVEL_MAP[a.level] - LEVEL_MAP[b.level]); +export interface DeprecationResolutionState { + id: string; + resolveDeprecationStatus: 'ok' | 'fail' | 'in_progress'; + resolveDeprecationError?: string; +} + +export interface KibanaDeprecationDetails extends DomainDeprecationDetails { + id: string; + filterType: DomainDeprecationDetails['deprecationType'] | 'uncategorized'; +} + +const getDeprecationCountByLevel = (deprecations: KibanaDeprecationDetails[]) => { + const criticalDeprecations: KibanaDeprecationDetails[] = []; + const warningDeprecations: KibanaDeprecationDetails[] = []; + + deprecations.forEach((deprecation) => { + if (deprecation.level === 'critical') { + criticalDeprecations.push(deprecation); + return; + } + warningDeprecations.push(deprecation); + }); + + return { + criticalDeprecations: criticalDeprecations.length, + warningDeprecations: warningDeprecations.length, + }; }; -export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponentProps) => { +export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) => { const [kibanaDeprecations, setKibanaDeprecations] = useState< - DomainDeprecationDetails[] | undefined + KibanaDeprecationDetails[] | undefined >(undefined); + const [kibanaDeprecationErrors, setKibanaDeprecationErrors] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(undefined); - const [stepsModalContent, setStepsModalContent] = useState( + const [flyoutContent, setFlyoutContent] = useState( undefined ); - const [resolveModalContent, setResolveModalContent] = useState< - undefined | DomainDeprecationDetails + const [deprecationResolutionState, setDeprecationResolutionState] = useState< + DeprecationResolutionState | undefined >(undefined); - const [isResolvingDeprecation, setIsResolvingDeprecation] = useState(false); const { services: { - core: { deprecations, docLinks, notifications }, + core: { deprecations }, breadcrumbs, api, }, } = useAppContext(); + const { + addContent: addContentToGlobalFlyout, + removeContent: removeContentFromGlobalFlyout, + } = useGlobalFlyout(); + const getAllDeprecations = useCallback(async () => { setIsLoading(true); try { - const response = await deprecations.getAllDeprecations(); - const sortedDeprecations = response.sort(sortByLevelDesc); - setKibanaDeprecations(sortedDeprecations); + const allDeprecations = await deprecations.getAllDeprecations(); + + const filteredDeprecations: KibanaDeprecationDetails[] = []; + const deprecationErrors: string[] = []; + + allDeprecations.forEach((deprecation) => { + // Keep track of any deprecations that failed to fetch to show warning in UI + if (deprecation.level === 'fetch_error') { + deprecationErrors.push(deprecation.domainId); + return; + } + + // Only show deprecations in the table that fetched successfully + filteredDeprecations.push({ + ...deprecation, + id: uuid.v4(), // Associate an unique ID with each deprecation to track resolution state + filterType: deprecation.deprecationType ?? 'uncategorized', // deprecationType is currently optional, in order to correctly handle sort/filter, we default any undefined types to "uncategorized" + }); + }); + + setKibanaDeprecations(filteredDeprecations); + setKibanaDeprecationErrors(deprecationErrors); } catch (e) { setError(e); } @@ -86,35 +167,68 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent setIsLoading(false); }, [deprecations]); - const toggleStepsModal = (newStepsModalContent?: StepsModalContent) => { - setStepsModalContent(newStepsModalContent); - }; + const deprecationsCountByLevel: { + warningDeprecations: number; + criticalDeprecations: number; + } = useMemo(() => getDeprecationCountByLevel(kibanaDeprecations || []), [kibanaDeprecations]); - const toggleResolveModal = (newResolveModalContent?: DomainDeprecationDetails) => { - setResolveModalContent(newResolveModalContent); + const toggleFlyout = (newFlyoutContent?: KibanaDeprecationDetails) => { + setFlyoutContent(newFlyoutContent); }; - const resolveDeprecation = async (deprecationDetails: DomainDeprecationDetails) => { - setIsResolvingDeprecation(true); + const closeFlyout = useCallback(() => { + toggleFlyout(); + removeContentFromGlobalFlyout('deprecationDetails'); + }, [removeContentFromGlobalFlyout]); - const response = await deprecations.resolveDeprecation(deprecationDetails); + const resolveDeprecation = useCallback( + async (deprecationDetails: KibanaDeprecationDetails) => { + setDeprecationResolutionState({ + id: deprecationDetails.id, + resolveDeprecationStatus: 'in_progress', + }); - setIsResolvingDeprecation(false); - toggleResolveModal(); + const response = await deprecations.resolveDeprecation(deprecationDetails); - // Handle error case - if (response.status === 'fail') { - notifications.toasts.addError(new Error(response.reason), { - title: i18nTexts.errorMessage, + setDeprecationResolutionState({ + id: deprecationDetails.id, + resolveDeprecationStatus: response.status, + resolveDeprecationError: response.status === 'fail' ? response.reason : undefined, }); - return; - } + closeFlyout(); + }, + [closeFlyout, deprecations] + ); - notifications.toasts.addSuccess(i18nTexts.successMessage); - // Refetch deprecations - getAllDeprecations(); - }; + useEffect(() => { + if (flyoutContent) { + addContentToGlobalFlyout({ + id: 'deprecationDetails', + Component: DeprecationDetailsFlyout, + props: { + deprecation: flyoutContent, + closeFlyout, + resolveDeprecation, + deprecationResolutionState: + deprecationResolutionState && flyoutContent.id === deprecationResolutionState.id + ? deprecationResolutionState + : undefined, + }, + flyoutProps: { + onClose: closeFlyout, + 'data-test-subj': 'kibanaDeprecationDetails', + 'aria-labelledby': 'kibanaDeprecationDetailsFlyoutTitle', + }, + }); + } + }, [ + addContentToGlobalFlyout, + closeFlyout, + deprecationResolutionState, + flyoutContent, + resolveDeprecation, + ]); useEffect(() => { async function sendTelemetryData() { @@ -151,51 +265,64 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent {i18nTexts.isLoading} ); - } else if (kibanaDeprecations?.length) { + } + + if (kibanaDeprecations?.length) { return ( -
+
- {i18nTexts.docLinkText} - , - ]} - /> + > + + - + {kibanaDeprecationErrors.length > 0 && ( + <> + +

{i18nTexts.getKibanaDeprecationErrorDescription(kibanaDeprecationErrors)}

+
- {stepsModalContent && ( - toggleStepsModal()} modalContent={stepsModalContent} /> + + )} - {resolveModalContent && ( - toggleResolveModal()} - resolveDeprecation={resolveDeprecation} - isResolvingDeprecation={isResolvingDeprecation} - deprecation={resolveModalContent} - /> - )} +
); - } else if (error) { - return ; + } + + if (error) { + return ( + + {i18nTexts.requestErrorTitle}} + body={

{i18nTexts.requestErrorDescription}

} + /> +
+ ); } return null; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx new file mode 100644 index 0000000000000..9117bcdbcaee5 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx @@ -0,0 +1,251 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiInMemoryTable, + EuiBasicTableColumn, + EuiButton, + EuiLink, + EuiBadge, + Search, +} from '@elastic/eui'; + +import { PAGINATION_CONFIG } from '../constants'; +import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; +import { ResolutionTableCell } from './resolution_table_cell'; + +const i18nTexts = { + refreshButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.refreshButtonLabel', + { + defaultMessage: 'Refresh', + } + ), + statusColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.statusColumnTitle', + { + defaultMessage: 'Status', + } + ), + issueColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.issueColumnTitle', + { + defaultMessage: 'Issue', + } + ), + typeColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.typeColumnTitle', + { + defaultMessage: 'Type', + } + ), + resolutionColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.resolutionColumnTitle', + { + defaultMessage: 'Resolution', + } + ), + configDeprecationTypeCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.configDeprecationTypeCellLabel', + { + defaultMessage: 'Config', + } + ), + featureDeprecationTypeCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.featureDeprecationTypeCellLabel', + { + defaultMessage: 'Feature', + } + ), + unknownDeprecationTypeCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.unknownDeprecationTypeCellLabel', + { + defaultMessage: 'Uncategorized', + } + ), + typeFilterLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.typeFilterLabel', + { + defaultMessage: 'Type', + } + ), + criticalFilterLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.criticalFilterLabel', + { + defaultMessage: 'Critical', + } + ), + criticalBadgeLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.criticalBadgeLabel', + { + defaultMessage: 'critical', + } + ), + searchPlaceholderLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.searchPlaceholderLabel', + { + defaultMessage: 'Filter', + } + ), +}; + +interface Props { + deprecations?: KibanaDeprecationDetails[]; + reload: () => void; + toggleFlyout: (newFlyoutContent?: KibanaDeprecationDetails) => void; + deprecationResolutionState?: DeprecationResolutionState; +} + +export const KibanaDeprecationsTable: React.FunctionComponent = ({ + deprecations, + reload, + toggleFlyout, + deprecationResolutionState, +}) => { + const columns: Array> = [ + { + field: 'level', + name: i18nTexts.statusColumnTitle, + width: '5%', + truncateText: true, + sortable: true, + render: (level: KibanaDeprecationDetails['level']) => { + if (level === 'critical') { + return {i18nTexts.criticalBadgeLabel}; + } + + return <>{''}; + }, + }, + { + field: 'title', + width: '40%', + name: i18nTexts.issueColumnTitle, + truncateText: true, + sortable: true, + render: (title: KibanaDeprecationDetails['title'], deprecation: KibanaDeprecationDetails) => { + return ( + toggleFlyout(deprecation)} + data-test-subj="deprecationDetailsLink" + > + {title} + + ); + }, + }, + { + field: 'filterType', + name: i18nTexts.typeColumnTitle, + width: '20%', + truncateText: true, + sortable: true, + render: (filterType: KibanaDeprecationDetails['filterType']) => { + switch (filterType) { + case 'config': + return i18nTexts.configDeprecationTypeCellLabel; + case 'feature': + return i18nTexts.featureDeprecationTypeCellLabel; + case 'uncategorized': + default: + return i18nTexts.unknownDeprecationTypeCellLabel; + } + }, + }, + { + field: 'correctiveActions', + name: i18nTexts.resolutionColumnTitle, + width: '30%', + truncateText: true, + sortable: true, + render: ( + correctiveActions: KibanaDeprecationDetails['correctiveActions'], + deprecation: KibanaDeprecationDetails + ) => { + return ( + + ); + }, + }, + ]; + + const sorting = { + sort: { + field: 'level', + direction: 'asc', + }, + } as const; + + const searchConfig: Search = { + filters: [ + { + type: 'field_value_toggle', + name: i18nTexts.criticalFilterLabel, + field: 'level', + value: 'critical', + }, + { + type: 'field_value_selection', + field: 'filterType', + name: i18nTexts.typeFilterLabel, + multiSelect: false, + options: [ + { + value: 'config', + name: i18nTexts.configDeprecationTypeCellLabel, + }, + { + value: 'feature', + name: i18nTexts.featureDeprecationTypeCellLabel, + }, + { + value: 'uncategorized', + name: i18nTexts.unknownDeprecationTypeCellLabel, + }, + ], + }, + ], + box: { + incremental: true, + placeholder: i18nTexts.searchPlaceholderLabel, + }, + toolsRight: [ + + {i18nTexts.refreshButtonLabel} + , + ], + }; + + return ( + ({ + 'data-test-subj': 'row', + })} + cellProps={(deprecation, field) => ({ + 'data-test-subj': `${((field?.name as string) || 'table').toLowerCase()}Cell`, + })} + data-test-subj="kibanaDeprecationsTable" + tableLayout="auto" + /> + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx new file mode 100644 index 0000000000000..aef52fe07a183 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { + EuiFlexItem, + EuiText, + EuiFlexGroup, + EuiIcon, + EuiLoadingSpinner, + EuiToolTip, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import type { DeprecationResolutionState } from './kibana_deprecations'; + +const i18nTexts = { + manualCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.manualCellLabel', + { + defaultMessage: 'Manual', + } + ), + manualCellTooltipLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.manualCellTooltipLabel', + { + defaultMessage: 'Resolve this deprecation manually.', + } + ), + automatedCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automatedCellLabel', + { + defaultMessage: 'Automated', + } + ), + automationInProgressCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automationInProgressCellLabel', + { + defaultMessage: 'Resolution in progress…', + } + ), + automationCompleteCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automationCompleteCellLabel', + { + defaultMessage: 'Resolved', + } + ), + automationFailedCellLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automationFailedCellLabel', + { + defaultMessage: 'Resolution failed', + } + ), + automatedCellTooltipLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.automatedCellTooltipLabel', + { + defaultMessage: 'This is an automated resolution.', + } + ), +}; + +interface Props { + deprecationId: string; + isAutomated: boolean; + deprecationResolutionState?: DeprecationResolutionState; +} + +export const ResolutionTableCell: React.FunctionComponent = ({ + deprecationId, + isAutomated, + deprecationResolutionState, +}) => { + if (isAutomated) { + if (deprecationResolutionState?.id === deprecationId) { + const { resolveDeprecationStatus } = deprecationResolutionState; + + switch (resolveDeprecationStatus) { + case 'in_progress': + return ( + + + + + + {i18nTexts.automationInProgressCellLabel} + + + ); + case 'fail': + return ( + + + + + + {i18nTexts.automationFailedCellLabel} + + + ); + case 'ok': + default: + return ( + + + + + + {i18nTexts.automationCompleteCellLabel} + + + ); + } + } + + return ( + + + + + + + {i18nTexts.automatedCellLabel} + + + + ); + } + + return ( + + + {i18nTexts.manualCellLabel} + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx deleted file mode 100644 index f94512fac5630..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { EuiConfirmModal } from '@elastic/eui'; -import type { DomainDeprecationDetails } from 'kibana/public'; - -interface Props { - closeModal: () => void; - deprecation: DomainDeprecationDetails; - isResolvingDeprecation: boolean; - resolveDeprecation: (deprecationDetails: DomainDeprecationDetails) => Promise; -} - -const i18nTexts = { - getModalTitle: (domainId: string) => - i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle', - { - defaultMessage: "Resolve deprecation in '{domainId}'?", - values: { - domainId, - }, - } - ), - cancelButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.cancelButtonLabel', - { - defaultMessage: 'Cancel', - } - ), - resolveButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.resolveButtonLabel', - { - defaultMessage: 'Resolve', - } - ), -}; - -export const ResolveDeprecationModal: FunctionComponent = ({ - closeModal, - deprecation, - isResolvingDeprecation, - resolveDeprecation, -}) => { - return ( - resolveDeprecation(deprecation)} - cancelButtonText={i18nTexts.cancelButtonLabel} - confirmButtonText={i18nTexts.resolveButtonLabel} - defaultFocusedButton="confirm" - isLoading={isResolvingDeprecation} - /> - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx deleted file mode 100644 index 98027d4f46aac..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { - EuiText, - EuiSteps, - EuiButton, - EuiModal, - EuiModalBody, - EuiModalFooter, - EuiModalHeader, - EuiModalHeaderTitle, - EuiTitle, - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, -} from '@elastic/eui'; - -export interface StepsModalContent { - domainId: string; - steps: string[]; - documentationUrl?: string; -} - -interface Props { - closeModal: () => void; - modalContent: StepsModalContent; -} - -const i18nTexts = { - getModalTitle: (domainId: string) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle', { - defaultMessage: "Resolve deprecation in '{domainId}'", - values: { - domainId, - }, - }), - getStepTitle: (step: number) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.stepTitle', { - defaultMessage: 'Step {step}', - values: { - step, - }, - }), - docLinkLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel', - { - defaultMessage: 'View documentation', - } - ), - closeButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.closeButtonLabel', - { - defaultMessage: 'Close', - } - ), -}; - -export const StepsModal: FunctionComponent = ({ closeModal, modalContent }) => { - const { domainId, steps, documentationUrl } = modalContent; - - return ( - - - - -

{i18nTexts.getModalTitle(domainId)}

-
-
-
- - - { - return { - title: i18nTexts.getStepTitle(index + 1), - children: ( - -

{step}

-
- ), - }; - })} - /> -
- - - - {documentationUrl && ( - - - {i18nTexts.docLinkLabel} - - - )} - - - - {i18nTexts.closeButtonLabel} - - - - -
- ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx index 2f034d461a24f..bed92d3b92ccf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx @@ -11,12 +11,9 @@ import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon, EuiSpacer } from '@elastic import { i18n } from '@kbn/i18n'; const i18nTexts = { - noDeprecationsText: i18n.translate( - 'xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText', - { - defaultMessage: 'No warnings. Good to go!', - } - ), + noDeprecationsText: i18n.translate('xpack.upgradeAssistant.noDeprecationsText', { + defaultMessage: 'No warnings. Good to go!', + }), }; export const NoDeprecations: FunctionComponent = () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx new file mode 100644 index 0000000000000..3312508a87073 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; + +import { EuiFlexGroup, EuiFlexItem, EuiHealth } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +const i18nTexts = { + getCriticalStatusLabel: (count: number) => + i18n.translate('xpack.upgradeAssistant.deprecationCount.criticalStatusLabel', { + defaultMessage: 'Critical: {count}', + values: { + count, + }, + }), + getWarningStatusLabel: (count: number) => + i18n.translate('xpack.upgradeAssistant.deprecationCount.warningStatusLabel', { + defaultMessage: 'Warning: {count}', + values: { + count, + }, + }), +}; + +interface Props { + totalCriticalDeprecations: number; + totalWarningDeprecations: number; +} + +export const DeprecationCount: FunctionComponent = ({ + totalCriticalDeprecations, + totalWarningDeprecations, +}) => { + return ( + + + + {i18nTexts.getCriticalStatusLabel(totalCriticalDeprecations)} + + + + + {i18nTexts.getWarningStatusLabel(totalWarningDeprecations)} + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx deleted file mode 100644 index 709ef7224870e..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent } from 'react'; - -import { EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export const DeprecationCountSummary: FunctionComponent<{ - allDeprecationsCount: number; - filteredDeprecationsCount: number; -}> = ({ filteredDeprecationsCount, allDeprecationsCount }) => ( - - {allDeprecationsCount > 0 ? ( - - ) : ( - - )} - {filteredDeprecationsCount !== allDeprecationsCount && ( - <> - {'. '} - - - )} - -); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx deleted file mode 100644 index 6cb5ae3675c44..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { DeprecationCountSummary } from './count_summary'; - -const i18nTexts = { - expandAllButton: i18n.translate( - 'xpack.upgradeAssistant.deprecationListBar.expandAllButtonLabel', - { - defaultMessage: 'Expand all', - } - ), - collapseAllButton: i18n.translate( - 'xpack.upgradeAssistant.deprecationListBar.collapseAllButtonLabel', - { - defaultMessage: 'Collapse all', - } - ), -}; - -export const DeprecationListBar: FunctionComponent<{ - allDeprecationsCount: number; - filteredDeprecationsCount: number; - setExpandAll: (shouldExpandAll: boolean) => void; -}> = ({ allDeprecationsCount, filteredDeprecationsCount, setExpandAll }) => { - return ( - - - - - - - - - setExpandAll(true)} - data-test-subj="expandAll" - > - {i18nTexts.expandAllButton} - - - - setExpandAll(false)} - data-test-subj="collapseAll" - > - {i18nTexts.collapseAllButton} - - - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx deleted file mode 100644 index ae2c0ba1c4877..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent } from 'react'; - -import { EuiFlexGroup, EuiFlexItem, EuiPagination } from '@elastic/eui'; - -export const DeprecationPagination: FunctionComponent<{ - pageCount: number; - activePage: number; - setPage: (page: number) => void; -}> = ({ pageCount, activePage, setPage }) => { - return ( - - - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx deleted file mode 100644 index 9bf35668ac88a..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { countBy } from 'lodash'; -import React, { FunctionComponent } from 'react'; - -import { EuiBadge, EuiToolTip } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { DeprecationInfo } from '../../../../common/types'; -import { COLOR_MAP, REVERSE_LEVEL_MAP } from '../constants'; - -const LocalizedLevels: { [level: string]: string } = { - warning: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.warningLabel', { - defaultMessage: 'Warning', - }), - critical: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel', { - defaultMessage: 'Critical', - }), -}; - -export const LocalizedActions: { [level: string]: string } = { - warning: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.warningActionTooltip', { - defaultMessage: 'Resolving this issue before upgrading is advised, but not required.', - }), - critical: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip', { - defaultMessage: 'Resolve this issue before upgrading.', - }), -}; - -interface DeprecationHealthProps { - deprecationLevels: number[]; - single?: boolean; -} - -const SingleHealth: FunctionComponent<{ level: DeprecationInfo['level']; label: string }> = ({ - level, - label, -}) => ( - - - {label} - -   - -); - -/** - * Displays a summary health for a list of deprecations that shows the number and level of severity - * deprecations in the list. - */ -export const DeprecationHealth: FunctionComponent = ({ - deprecationLevels, - single = false, -}) => { - if (deprecationLevels.length === 0) { - return ; - } - - if (single) { - const highest = Math.max(...deprecationLevels); - const highestLevel = REVERSE_LEVEL_MAP[highest]; - - return ; - } - - const countByLevel = countBy(deprecationLevels); - - return ( - - {Object.keys(countByLevel) - .map((k) => parseInt(k, 10)) - .sort() - .map((level) => [level, REVERSE_LEVEL_MAP[level]]) - .map(([numLevel, stringLevel]) => ( - - ))} - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts index c79d8247a93f1..89bce0813b92f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts @@ -6,7 +6,4 @@ */ export { NoDeprecationsPrompt } from './no_deprecations'; -export { DeprecationHealth } from './health'; -export { SearchBar } from './search_bar'; -export { DeprecationPagination } from './deprecation_pagination'; -export { DeprecationListBar } from './deprecation_list_bar'; +export { DeprecationCount } from './deprecation_count'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap deleted file mode 100644 index 5a8619e1e687b..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap +++ /dev/null @@ -1,24 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`GroupByFilter renders 1`] = ` - - - - By issue - - - By index - - - -`; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap deleted file mode 100644 index 551e212f23dd7..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DeprecationLevelFilter renders 1`] = ` - - - - Critical - - - -`; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx deleted file mode 100644 index fa863e4935c09..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { mount, shallow } from 'enzyme'; -import React from 'react'; - -import { GroupByOption } from '../../types'; -import { GroupByFilter } from './group_by_filter'; - -const defaultProps = { - availableGroupByOptions: [GroupByOption.message, GroupByOption.index], - currentGroupBy: GroupByOption.message, - onGroupByChange: jest.fn(), -}; - -describe('GroupByFilter', () => { - test('renders', () => { - expect(shallow()).toMatchSnapshot(); - }); - - test('clicking button calls onGroupByChange', () => { - const wrapper = mount(); - wrapper.find('button.euiFilterButton-hasActiveFilters').simulate('click'); - expect(defaultProps.onGroupByChange).toHaveBeenCalledTimes(1); - expect(defaultProps.onGroupByChange.mock.calls[0][0]).toEqual(GroupByOption.message); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx deleted file mode 100644 index c37ae47793b95..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { EuiFilterButton, EuiFilterGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { GroupByOption } from '../../types'; - -const LocalizedOptions: { [option: string]: string } = { - message: i18n.translate('xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel', { - defaultMessage: 'By issue', - }), - index: i18n.translate('xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel', { - defaultMessage: 'By index', - }), -}; - -interface GroupByFilterProps { - availableGroupByOptions: GroupByOption[]; - currentGroupBy: GroupByOption; - onGroupByChange: (groupBy: GroupByOption) => void; -} - -export const GroupByFilter: React.FunctionComponent = ({ - availableGroupByOptions, - currentGroupBy, - onGroupByChange, -}) => { - if (availableGroupByOptions.length <= 1) { - return null; - } - - return ( - - - {availableGroupByOptions.map((option) => ( - - {LocalizedOptions[option]} - - ))} - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts deleted file mode 100644 index 31ad78cf572fe..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export { SearchBar } from './search_bar'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx deleted file mode 100644 index c778e56e8df11..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { mount, shallow } from 'enzyme'; -import React from 'react'; -import { LevelFilterOption } from '../../types'; - -import { DeprecationLevelFilter } from './level_filter'; - -const defaultProps = { - levelsCount: { - warning: 4, - critical: 1, - }, - currentFilter: 'all' as LevelFilterOption, - onFilterChange: jest.fn(), -}; - -describe('DeprecationLevelFilter', () => { - test('renders', () => { - expect(shallow()).toMatchSnapshot(); - }); - - test('clicking button calls onFilterChange', () => { - const wrapper = mount(); - wrapper.find('button[data-test-subj="criticalLevelFilter"]').simulate('click'); - expect(defaultProps.onFilterChange).toHaveBeenCalledTimes(1); - expect(defaultProps.onFilterChange.mock.calls[0][0]).toEqual('critical'); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx deleted file mode 100644 index 59bfaa595b0a6..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { EuiFilterButton, EuiFilterGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { LevelFilterOption } from '../../types'; - -const LocalizedOptions: { [option: string]: string } = { - critical: i18n.translate( - 'xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel', - { defaultMessage: 'Critical' } - ), -}; -interface DeprecationLevelProps { - levelsCount: { - [key: string]: number; - }; - currentFilter: LevelFilterOption; - onFilterChange(level: LevelFilterOption): void; -} - -export const DeprecationLevelFilter: React.FunctionComponent = ({ - levelsCount, - currentFilter, - onFilterChange, -}) => { - return ( - - - { - onFilterChange(currentFilter !== 'critical' ? 'critical' : 'all'); - }} - hasActiveFilters={currentFilter === 'critical'} - numFilters={levelsCount.critical || undefined} - data-test-subj="criticalLevelFilter" - > - {LocalizedOptions.critical} - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx deleted file mode 100644 index 7c805398a6b47..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiButton, - EuiFieldSearch, - EuiFlexGroup, - EuiFlexItem, - EuiCallOut, - EuiSpacer, -} from '@elastic/eui'; - -import type { DomainDeprecationDetails } from 'kibana/public'; -import { DeprecationInfo } from '../../../../../common/types'; -import { validateRegExpString } from '../../../lib/utils'; -import { GroupByOption, LevelFilterOption } from '../../types'; -import { DeprecationLevelFilter } from './level_filter'; -import { GroupByFilter } from './group_by_filter'; - -interface SearchBarProps { - allDeprecations?: DeprecationInfo[] | DomainDeprecationDetails; - isLoading: boolean; - loadData: () => void; - currentFilter: LevelFilterOption; - onFilterChange: (filter: LevelFilterOption) => void; - onSearchChange: (filter: string) => void; - totalDeprecationsCount: number; - levelToDeprecationCountMap: { - [key: string]: number; - }; - groupByFilterProps?: { - availableGroupByOptions: GroupByOption[]; - currentGroupBy: GroupByOption; - onGroupByChange: (groupBy: GroupByOption) => void; - }; -} - -const i18nTexts = { - searchAriaLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationListSearchBar.placeholderAriaLabel', - { defaultMessage: 'Filter' } - ), - searchPlaceholderLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationListSearchBar.placeholderLabel', - { - defaultMessage: 'Filter', - } - ), - reloadButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.deprecationListSearchBar.reloadButtonLabel', - { - defaultMessage: 'Reload', - } - ), - getInvalidSearchMessage: (searchTermError: string) => - i18n.translate('xpack.upgradeAssistant.deprecationListSearchBar.filterErrorMessageLabel', { - defaultMessage: 'Filter invalid: {searchTermError}', - values: { searchTermError }, - }), -}; - -export const SearchBar: FunctionComponent = ({ - totalDeprecationsCount, - levelToDeprecationCountMap, - isLoading, - loadData, - currentFilter, - onFilterChange, - onSearchChange, - groupByFilterProps, -}) => { - const [searchTermError, setSearchTermError] = useState(null); - const filterInvalid = Boolean(searchTermError); - return ( - <> - - - - - { - const string = e.target.value; - const errorMessage = validateRegExpString(string); - if (errorMessage) { - // Emit an empty search term to listeners if search term is invalid. - onSearchChange(''); - setSearchTermError(errorMessage); - } else { - onSearchChange(e.target.value); - if (searchTermError) { - setSearchTermError(null); - } - } - }} - /> - - - {/* These two components provide their own EuiFlexItem wrappers */} - - {groupByFilterProps && } - - - - - {i18nTexts.reloadButtonLabel} - - - - - {filterInvalid && ( - <> - - - - - )} - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts index b46bb583244f0..81495c45420bf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts @@ -13,14 +13,6 @@ export enum LoadingState { Error, } -export type LevelFilterOption = 'all' | 'critical'; - -export enum GroupByOption { - message = 'message', - index = 'index', - node = 'node', -} - export type DeprecationTableColumns = | 'type' | 'index' diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts index f36dc2096ddc7..1beb759442f9f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts @@ -21,7 +21,7 @@ const i18nTexts = { kibanaDeprecations: i18n.translate( 'xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel', { - defaultMessage: 'Kibana deprecations', + defaultMessage: 'Kibana deprecation warnings', } ), }, diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 47bade2e706d1..01fc11954ef76 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -75,22 +75,38 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - it('Kibana deprecations page', async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/kibana_deprecations', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); + describe('Kibana deprecations page', () => { + beforeEach(async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/kibana_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); - await retry.waitFor('Kibana deprecations to be visible', async () => { - return testSubjects.exists('kibanaDeprecationsContent'); + await retry.waitFor('Kibana deprecations to be visible', async () => { + return testSubjects.exists('kibanaDeprecations'); + }); }); - await a11y.testAppSnapshot(); + it('Deprecations table', async () => { + await a11y.testAppSnapshot(); + }); + + it('Deprecation details flyout', async () => { + await PageObjects.upgradeAssistant.clickKibanaDeprecation( + 'xpack.securitySolution has a deprecated setting' // This deprecation was added to the test runner config so should be guaranteed + ); + + await retry.waitFor('Kibana deprecation details flyout to be visible', async () => { + return testSubjects.exists('kibanaDeprecationDetails'); + }); + + await a11y.testAppSnapshot(); + }); }); }); } diff --git a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts index fec341de6c09e..99d77a2423f47 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts @@ -106,7 +106,7 @@ export default function upgradeAssistantFunctionalTests({ await PageObjects.upgradeAssistant.clickKibanaDeprecationsPanel(); await retry.waitFor('Kibana deprecations table to be visible', async () => { - return testSubjects.exists('kibanaDeprecationsContent'); + return testSubjects.exists('kibanaDeprecations'); }); }); }); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 0b202d3eb1b54..8825c5796496f 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -86,6 +86,9 @@ export default async function ({ readConfigFile }) { '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', '--xpack.discoverEnhanced.actions.exploreDataInContextMenu.enabled=true', '--savedObjects.maxImportPayloadBytes=10485760', // for OSS test management/_import_objects + '--xpack.observability.unsafe.cases.enabled=true', + '--xpack.siem.enabled=true', // Used to trigger Kibana deprecation warning in UA (renamed config) + '--xpack.observability.unsafe.alertingExperience.enabled=true', // NOTE: Can be removed once enabled by default ], }, uiSettings: { diff --git a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts index 32332620ffc59..406800d775417 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts +++ b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts @@ -40,4 +40,21 @@ export class UpgradeAssistantPageObject extends FtrService { await this.testSubjects.click('kibanaStatsPanel'); }); } + + async clickKibanaDeprecation(selectedIssue: string) { + const table = await this.testSubjects.find('kibanaDeprecationsTable'); + const rows = await table.findAllByTestSubject('row'); + + const selectedRow = rows.find(async (row) => { + const issue = await (await row.findByTestSubject('issueCell')).getVisibleText(); + return issue === selectedIssue; + }); + + if (selectedRow) { + const issueLink = await selectedRow.findByTestSubject('deprecationDetailsLink'); + await issueLink.click(); + } else { + this.log.debug('Unable to find selected deprecation row'); + } + } } From 9a2c58a6de1a37f61601811855959cc73f3981b5 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 3 Sep 2021 14:05:39 -0700 Subject: [PATCH 16/93] Use injected lib.handleEsError instead of importing it in Upgrade Assistant API route handlers. (#111067) --- .../server/routes/es_deprecations.test.ts | 3 +++ .../server/routes/es_deprecations.ts | 12 ++++++++---- .../server/routes/ml_snapshots.test.ts | 3 +++ .../upgrade_assistant/server/routes/ml_snapshots.ts | 7 +++---- .../upgrade_assistant/server/routes/status.test.ts | 3 +++ .../upgrade_assistant/server/routes/status.ts | 7 +++---- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.test.ts index bea74f116e0e2..4047ce827acbc 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.test.ts @@ -6,6 +6,8 @@ */ import { kibanaResponseFactory } from 'src/core/server'; + +import { handleEsError } from '../shared_imports'; import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; @@ -33,6 +35,7 @@ describe('ES deprecations API', () => { mockRouter = createMockRouter(); routeDependencies = { router: mockRouter, + lib: { handleEsError }, }; registerESDeprecationRoutes(routeDependencies); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.ts b/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.ts index eb0ade26de766..98089e34bdca1 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/es_deprecations.ts @@ -11,9 +11,13 @@ import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { RouteDependencies } from '../types'; import { reindexActionsFactory } from '../lib/reindexing/reindex_actions'; import { reindexServiceFactory } from '../lib/reindexing'; -import { handleEsError } from '../shared_imports'; -export function registerESDeprecationRoutes({ router, licensing, log }: RouteDependencies) { +export function registerESDeprecationRoutes({ + router, + lib: { handleEsError }, + licensing, + log, +}: RouteDependencies) { router.get( { path: `${API_BASE_PATH}/es_deprecations`, @@ -50,8 +54,8 @@ export function registerESDeprecationRoutes({ router, licensing, log }: RouteDep return response.ok({ body: status, }); - } catch (e) { - return handleEsError({ error: e, response }); + } catch (error) { + return handleEsError({ error, response }); } } ) diff --git a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts index 2f8cdd2aba808..2e53f571ee904 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts @@ -6,6 +6,8 @@ */ import { kibanaResponseFactory, RequestHandler } from 'src/core/server'; + +import { handleEsError } from '../shared_imports'; import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; import { registerMlSnapshotRoutes } from './ml_snapshots'; @@ -26,6 +28,7 @@ describe('ML snapshots APIs', () => { mockRouter = createMockRouter(); routeDependencies = { router: mockRouter, + lib: { handleEsError }, }; registerMlSnapshotRoutes(routeDependencies); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts index 65e707339d67c..df977c4c9a157 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts @@ -11,7 +11,6 @@ import { IScopedClusterClient, SavedObjectsClientContract } from 'kibana/server' import { API_BASE_PATH } from '../../common/constants'; import { MlOperation, ML_UPGRADE_OP_TYPE } from '../../common/types'; import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; -import { handleEsError } from '../shared_imports'; import { RouteDependencies } from '../types'; const findMlOperation = async ( @@ -99,7 +98,7 @@ const verifySnapshotUpgrade = async ( } }; -export function registerMlSnapshotRoutes({ router }: RouteDependencies) { +export function registerMlSnapshotRoutes({ router, lib: { handleEsError } }: RouteDependencies) { // Upgrade ML model snapshot router.post( { @@ -147,8 +146,8 @@ export function registerMlSnapshotRoutes({ router }: RouteDependencies) { status: body.completed === true ? 'complete' : 'in_progress', }, }); - } catch (e) { - return handleEsError({ error: e, response }); + } catch (error) { + return handleEsError({ error, response }); } } ) diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts index 36f8edb1fafee..8c0398ce86afc 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts @@ -6,6 +6,8 @@ */ import { kibanaResponseFactory } from 'src/core/server'; + +import { handleEsError } from '../shared_imports'; import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; import { registerUpgradeStatusRoute } from './status'; @@ -31,6 +33,7 @@ describe('Status API', () => { mockRouter = createMockRouter(); routeDependencies = { router: mockRouter, + lib: { handleEsError }, }; registerUpgradeStatusRoute(routeDependencies); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.ts index c0e917b2c3206..79c9baadcb852 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.ts @@ -11,9 +11,8 @@ import { getESUpgradeStatus } from '../lib/es_deprecations_status'; import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { getKibanaUpgradeStatus } from '../lib/kibana_status'; import { RouteDependencies } from '../types'; -import { handleEsError } from '../shared_imports'; -export function registerUpgradeStatusRoute({ router }: RouteDependencies) { +export function registerUpgradeStatusRoute({ router, lib: { handleEsError } }: RouteDependencies) { router.get( { path: `${API_BASE_PATH}/status`, @@ -63,8 +62,8 @@ export function registerUpgradeStatusRoute({ router }: RouteDependencies) { details: getStatusMessage(), }, }); - } catch (e) { - return handleEsError({ error: e, response }); + } catch (error) { + return handleEsError({ error, response }); } } ) From 5d1be87d2cd249ae729615d2497f211f70f6f63b Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Sun, 5 Sep 2021 18:01:14 -0700 Subject: [PATCH 17/93] Add tests for UA back up data step on Cloud (#111066) --- .../helpers/http_requests.ts | 32 ++++- .../helpers/setup_environment.tsx | 5 +- .../overview/backup_step/backup_step.test.tsx | 122 +++++++++++++++++- .../overview/backup_step/cloud_backup.tsx | 6 +- .../upgrade_assistant/cloud_backup_status.ts | 95 ++++++++++++++ .../apis/upgrade_assistant/index.ts | 1 + 6 files changed, 250 insertions(+), 11 deletions(-) create mode 100644 x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts index 924dce1a0be9f..2a3f7f5321b5b 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts @@ -7,11 +7,29 @@ import sinon, { SinonFakeServer } from 'sinon'; import { API_BASE_PATH } from '../../../common/constants'; -import { ESUpgradeStatus, DeprecationLoggingStatus } from '../../../common/types'; +import { + CloudBackupStatus, + ESUpgradeStatus, + DeprecationLoggingStatus, +} from '../../../common/types'; import { ResponseError } from '../../../public/application/lib/api'; // Register helpers to mock HTTP Requests const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { + const setLoadCloudBackupStatusResponse = ( + response?: CloudBackupStatus, + error?: ResponseError + ) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + + server.respondWith('GET', `${API_BASE_PATH}/cloud_backup_status`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + const setLoadEsDeprecationsResponse = (response?: ESUpgradeStatus, error?: ResponseError) => { const status = error ? error.statusCode || 400 : 200; const body = error ? error : response; @@ -109,6 +127,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { }; return { + setLoadCloudBackupStatusResponse, setLoadEsDeprecationsResponse, setLoadDeprecationLoggingResponse, setUpdateDeprecationLoggingResponse, @@ -131,8 +150,19 @@ export const init = () => { const httpRequestsMockHelpers = registerHttpRequestMockHelpers(server); + const setServerAsync = (isAsync: boolean, timeout: number = 200) => { + if (isAsync) { + server.autoRespond = true; + server.autoRespondAfter = 1000; + server.respondImmediately = false; + } else { + server.respondImmediately = true; + } + }; + return { server, + setServerAsync, httpRequestsMockHelpers, }; }; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx index e9104ea2d75a4..887672e0bb6cd 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx @@ -19,9 +19,9 @@ import { AppContextProvider } from '../../../public/application/app_context'; import { apiService } from '../../../public/application/lib/api'; import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; import { GlobalFlyout } from '../../../public/shared_imports'; +import { AppDependencies } from '../../../public/types'; import { getAppContextMock } from './app_context.mock'; import { init as initHttpRequests } from './http_requests'; -import { AppDependencies } from '../../../public/types'; const { GlobalFlyoutProvider } = GlobalFlyout; @@ -47,10 +47,11 @@ export const WithAppDependencies = (Comp: any, overrides: Record { - const { server, httpRequestsMockHelpers } = initHttpRequests(); + const { server, setServerAsync, httpRequestsMockHelpers } = initHttpRequests(); return { server, + setServerAsync, httpRequestsMockHelpers, }; }; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx index ab571790d56c6..c99aa7031aa3d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx @@ -5,27 +5,139 @@ * 2.0. */ +import { act } from 'react-dom/test-utils'; + import { setupEnvironment } from '../../helpers'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; describe('Overview - Backup Step', () => { let testBed: OverviewTestBed; - const { server } = setupEnvironment(); + let server: ReturnType['server']; + let setServerAsync: ReturnType['setServerAsync']; + let httpRequestsMockHelpers: ReturnType['httpRequestsMockHelpers']; - beforeEach(async () => { - testBed = await setupOverviewPage(); - testBed.component.update(); + beforeEach(() => { + ({ server, setServerAsync, httpRequestsMockHelpers } = setupEnvironment()); }); - afterAll(() => { + afterEach(() => { server.restore(); }); describe('On-prem', () => { + beforeEach(async () => { + testBed = await setupOverviewPage(); + }); + test('Shows link to Snapshot and Restore', () => { const { exists, find } = testBed; expect(exists('snapshotRestoreLink')).toBe(true); expect(find('snapshotRestoreLink').props().href).toBe('snapshotAndRestoreUrl'); }); }); + + describe('On Cloud', () => { + const setupCloudOverviewPage = async () => + setupOverviewPage({ + plugins: { + cloud: { + isCloudEnabled: true, + deploymentUrl: 'deploymentUrl', + }, + }, + }); + + describe('initial loading state', () => { + beforeEach(async () => { + // We don't want the request to load backup status to resolve immediately. + setServerAsync(true); + testBed = await setupCloudOverviewPage(); + }); + + afterEach(() => { + setServerAsync(false); + }); + + test('is rendered', () => { + const { exists } = testBed; + expect(exists('cloudBackupLoading')).toBe(true); + }); + }); + + describe('error state', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadCloudBackupStatusResponse(undefined, { + statusCode: 400, + message: 'error', + }); + + testBed = await setupCloudOverviewPage(); + }); + + test('is rendered', () => { + const { exists } = testBed; + testBed.component.update(); + expect(exists('cloudBackupErrorCallout')).toBe(true); + }); + + test('lets the user attempt to reload backup status', () => { + const { exists } = testBed; + testBed.component.update(); + expect(exists('cloudBackupRetryButton')).toBe(true); + }); + }); + + describe('success state', () => { + describe('when data is backed up', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadCloudBackupStatusResponse({ + isBackedUp: true, + lastBackupTime: '2021-08-25T19:59:59.863Z', + }); + + testBed = await setupCloudOverviewPage(); + }); + + test('renders link to Cloud backups and last backup time ', () => { + const { exists, find } = testBed; + expect(exists('dataBackedUpStatus')).toBe(true); + expect(exists('cloudSnapshotsLink')).toBe(true); + expect(find('dataBackedUpStatus').text()).toContain('Last snapshot created on'); + }); + }); + + describe(`when data isn't backed up`, () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadCloudBackupStatusResponse({ + isBackedUp: false, + lastBackupTime: undefined, + }); + + testBed = await setupCloudOverviewPage(); + }); + + test('renders link to Cloud backups and "not backed up" status', () => { + const { exists } = testBed; + expect(exists('dataNotBackedUpStatus')).toBe(true); + expect(exists('cloudSnapshotsLink')).toBe(true); + }); + }); + + test('polls for new status', async () => { + // The behavior we're testing involves state changes over time, so we need finer control over + // timing. + jest.useFakeTimers(); + testBed = await setupCloudOverviewPage(); + expect(server.requests.length).toBe(4); + + // Resolve the polling timeout. + await act(async () => { + jest.runAllTimers(); + }); + + expect(server.requests.length).toBe(5); + jest.useRealTimers(); + }); + }); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx index 2af9aa2e82702..e73cfaab8b2b6 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx @@ -38,7 +38,7 @@ export const CloudBackup: React.FunctionComponent = ({ const { isInitialRequest, isLoading, error, data, resendRequest } = cloudBackupStatusResponse; if (isInitialRequest && isLoading) { - return ; + return ; } if (error) { @@ -66,7 +66,7 @@ export const CloudBackup: React.FunctionComponent = ({ const lastBackupTime = moment(data!.lastBackupTime).toISOString(); const statusMessage = data!.isBackedUp ? ( - + @@ -96,7 +96,7 @@ export const CloudBackup: React.FunctionComponent = ({ ) : ( - + diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts b/x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts new file mode 100644 index 0000000000000..7095c115ae7e1 --- /dev/null +++ b/x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + + const CLOUD_SNAPSHOT_REPOSITORY = 'found-snapshots'; + + const createCloudRepository = () => { + return es.snapshot + .createRepository({ + repository: CLOUD_SNAPSHOT_REPOSITORY, + body: { + type: 'fs', + settings: { + location: '/tmp/cloud-snapshots/', + }, + }, + verify: false, + }) + .then(({ body }) => body); + }; + + const createCloudSnapshot = (snapshotName: string) => { + return es.snapshot.create({ + repository: CLOUD_SNAPSHOT_REPOSITORY, + snapshot: snapshotName, + wait_for_completion: true, + // Configure snapshot so no indices are captured, so the request completes ASAP. + body: { + indices: 'this_index_doesnt_exist', + ignore_unavailable: true, + include_global_state: false, + }, + }); + }; + + const deleteCloudSnapshot = (snapshotName: string) => { + return es.snapshot.delete({ + repository: CLOUD_SNAPSHOT_REPOSITORY, + snapshot: snapshotName, + }); + }; + + describe('Cloud backup status', () => { + describe('get', () => { + describe('with backups present', () => { + // Needs SnapshotInfo type https://github.com/elastic/elasticsearch-specification/issues/685 + let mostRecentSnapshot: any; + + before(async () => { + await createCloudRepository(); + await createCloudSnapshot('test_snapshot_1'); + mostRecentSnapshot = (await createCloudSnapshot('test_snapshot_2')).body.snapshot; + }); + + after(async () => { + await deleteCloudSnapshot('test_snapshot_1'); + await deleteCloudSnapshot('test_snapshot_2'); + }); + + it('returns status based on most recent snapshot', async () => { + const { body: cloudBackupStatus } = await supertest + .get('/api/upgrade_assistant/cloud_backup_status') + .set('kbn-xsrf', 'xxx') + .expect(200); + + expect(cloudBackupStatus.isBackedUp).to.be(true); + expect(cloudBackupStatus.lastBackupTime).to.be(mostRecentSnapshot.start_time); + }); + }); + + describe('without backups present', () => { + it('returns not-backed-up status', async () => { + const { body: cloudBackupStatus } = await supertest + .get('/api/upgrade_assistant/cloud_backup_status') + .set('kbn-xsrf', 'xxx') + .expect(200); + + expect(cloudBackupStatus.isBackedUp).to.be(false); + expect(cloudBackupStatus.lastBackupTime).to.be(undefined); + }); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/index.ts b/x-pack/test/api_integration/apis/upgrade_assistant/index.ts index 466d44ca460ac..ddb71c59423ba 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/index.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/index.ts @@ -10,5 +10,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Upgrade Assistant', () => { loadTestFile(require.resolve('./upgrade_assistant')); + loadTestFile(require.resolve('./cloud_backup_status')); }); } From 2bc4a35d572b66f154b310fc6a899ab574f541a1 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Mon, 6 Sep 2021 07:34:34 -0700 Subject: [PATCH 18/93] Update UA to consume snapshotsUrl as provided by the Cloud plugin. (#111239) --- .../application/components/overview/backup_step/backup_step.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx index 0e595dcbad1d6..b85f166e413f5 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx @@ -30,7 +30,7 @@ export const getBackupStep = ({ cloud, cloudBackupStatusResponse }: Props): EuiS children: ( ), }; From ccf1da61f6039c45b4542307450724173aab34f4 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 7 Sep 2021 07:57:21 -0700 Subject: [PATCH 19/93] Skip flaky UA Backup step polling test. --- .../overview/backup_step/backup_step.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx index c99aa7031aa3d..39a94ec458be4 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx @@ -123,7 +123,8 @@ describe('Overview - Backup Step', () => { }); }); - test('polls for new status', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/111255 + test.skip('polls for new status', async () => { // The behavior we're testing involves state changes over time, so we need finer control over // timing. jest.useFakeTimers(); From 4b3675f3fe56f25ad43060137cf818bb524a43a1 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 7 Sep 2021 18:06:21 -0400 Subject: [PATCH 20/93] [Upgrade Assistant] Refactor kibana deprecation service mocks (#111168) --- .../client_integration/helpers/index.ts | 1 + .../kibana_deprecations_service.mock.ts | 94 +++++++++++++++++++ .../deprecation_details_flyout.test.ts | 26 +++-- .../deprecations_list.test.ts | 45 ++++----- .../error_handling.test.ts | 35 +++---- .../kibana_deprecations/mocked_responses.ts | 34 ------- .../fix_issues_step/fix_issues_step.test.tsx | 37 +++++--- .../fix_issues_step/mocked_responses.ts | 18 ---- 8 files changed, 172 insertions(+), 118 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts delete mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts index 0c30e173ba994..7b20b8f7504a2 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts @@ -6,3 +6,4 @@ */ export { setupEnvironment, WithAppDependencies, kibanaVersion } from './setup_environment'; +export { kibanaDeprecationsServiceHelpers } from './kibana_deprecations_service.mock'; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts new file mode 100644 index 0000000000000..761f950bd7daf --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { DeprecationsServiceStart, DomainDeprecationDetails } from 'kibana/public'; + +const kibanaDeprecations: DomainDeprecationDetails[] = [ + { + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + api: { + method: 'POST', + path: '/test', + }, + }, + domainId: 'test_domain_1', + level: 'critical', + title: 'Test deprecation title 1', + message: 'Test deprecation message 1', + deprecationType: 'config', + }, + { + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + }, + domainId: 'test_domain_2', + level: 'warning', + title: 'Test deprecation title 1', + message: 'Test deprecation message 2', + deprecationType: 'feature', + }, +]; + +const setLoadDeprecations = ({ + deprecationService, + response, + mockRequestErrorMessage, +}: { + deprecationService: jest.Mocked; + response?: DomainDeprecationDetails[]; + mockRequestErrorMessage?: string; +}) => { + const mockResponse = response ? response : kibanaDeprecations; + + if (mockRequestErrorMessage) { + return deprecationService.getAllDeprecations.mockRejectedValue( + new Error(mockRequestErrorMessage) + ); + } + + return deprecationService.getAllDeprecations.mockReturnValue(Promise.resolve(mockResponse)); +}; + +const setResolveDeprecations = ({ + deprecationService, + status, +}: { + deprecationService: jest.Mocked; + status: 'ok' | 'fail'; +}) => { + if (status === 'fail') { + return deprecationService.resolveDeprecation.mockReturnValue( + Promise.resolve({ + status, + reason: 'resolve failed', + }) + ); + } + + return deprecationService.resolveDeprecation.mockReturnValue( + Promise.resolve({ + status, + }) + ); +}; + +export const kibanaDeprecationsServiceHelpers = { + setLoadDeprecations, + setResolveDeprecations, + defaultMockedResponses: { + mockedKibanaDeprecations: kibanaDeprecations, + mockedCriticalKibanaDeprecations: kibanaDeprecations.filter( + (deprecation) => deprecation.level === 'critical' + ), + mockedWarningKibanaDeprecations: kibanaDeprecations.filter( + (deprecation) => deprecation.level === 'warning' + ), + mockedConfigKibanaDeprecations: kibanaDeprecations.filter( + (deprecation) => deprecation.deprecationType === 'config' + ), + }, +}; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts index c65f15fda2e3c..f4f501221e595 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts @@ -8,13 +8,15 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; -import { setupEnvironment } from '../helpers'; +import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../helpers'; import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; -import { kibanaDeprecationsMockResponse } from './mocked_responses'; describe('Kibana deprecation details flyout', () => { let testBed: KibanaTestBed; const { server } = setupEnvironment(); + const { + defaultMockedResponses: { mockedKibanaDeprecations }, + } = kibanaDeprecationsServiceHelpers; const deprecationService = deprecationsServiceMock.createStartContract(); afterAll(() => { @@ -23,9 +25,7 @@ describe('Kibana deprecation details flyout', () => { beforeEach(async () => { await act(async () => { - deprecationService.getAllDeprecations = jest - .fn() - .mockReturnValue(kibanaDeprecationsMockResponse); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService }); testBed = await setupKibanaPage({ services: { @@ -42,7 +42,7 @@ describe('Kibana deprecation details flyout', () => { describe('Deprecation with manual steps', () => { test('renders flyout with manual steps only', async () => { const { find, exists, actions } = testBed; - const manualDeprecation = kibanaDeprecationsMockResponse[1]; + const manualDeprecation = mockedKibanaDeprecations[1]; await actions.table.clickDeprecationAt(1); @@ -61,7 +61,7 @@ describe('Kibana deprecation details flyout', () => { describe('Deprecation with automatic resolution', () => { test('resolves deprecation successfully', async () => { const { find, exists, actions } = testBed; - const quickResolveDeprecation = kibanaDeprecationsMockResponse[0]; + const quickResolveDeprecation = mockedKibanaDeprecations[0]; await actions.table.clickDeprecationAt(0); @@ -93,14 +93,12 @@ describe('Kibana deprecation details flyout', () => { test('handles resolve failure', async () => { const { find, exists, actions } = testBed; - const quickResolveDeprecation = kibanaDeprecationsMockResponse[0]; + const quickResolveDeprecation = mockedKibanaDeprecations[0]; - deprecationService.resolveDeprecation.mockReturnValue( - Promise.resolve({ - status: 'fail', - reason: 'resolve failed', - }) - ); + kibanaDeprecationsServiceHelpers.setResolveDeprecations({ + deprecationService, + status: 'fail', + }); await actions.table.clickDeprecationAt(0); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts index c3e3581409947..9a3b1d1882cc7 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts @@ -7,35 +7,32 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; +import type { DeprecationsServiceStart } from 'kibana/public'; -import { setupEnvironment } from '../helpers'; +import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../helpers'; import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; -import { kibanaDeprecationsMockResponse } from './mocked_responses'; - -const criticalDeprecations = kibanaDeprecationsMockResponse.filter( - (deprecation) => deprecation.level === 'critical' -); -const warningDeprecations = kibanaDeprecationsMockResponse.filter( - (deprecation) => deprecation.level === 'warning' -); -const configDeprecations = kibanaDeprecationsMockResponse.filter( - (deprecation) => deprecation.deprecationType === 'config' -); describe('Kibana deprecations table', () => { let testBed: KibanaTestBed; + let deprecationService: jest.Mocked; + const { server } = setupEnvironment(); - const deprecationService = deprecationsServiceMock.createStartContract(); + const { + mockedKibanaDeprecations, + mockedCriticalKibanaDeprecations, + mockedWarningKibanaDeprecations, + mockedConfigKibanaDeprecations, + } = kibanaDeprecationsServiceHelpers.defaultMockedResponses; afterAll(() => { server.restore(); }); beforeEach(async () => { + deprecationService = deprecationsServiceMock.createStartContract(); + await act(async () => { - deprecationService.getAllDeprecations = jest - .fn() - .mockReturnValue(kibanaDeprecationsMockResponse); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService }); testBed = await setupKibanaPage({ services: { @@ -56,7 +53,7 @@ describe('Kibana deprecations table', () => { const { tableCellsValues } = table.getMetaData('kibanaDeprecationsTable'); - expect(tableCellsValues.length).toEqual(kibanaDeprecationsMockResponse.length); + expect(tableCellsValues.length).toEqual(mockedKibanaDeprecations.length); }); it('refreshes deprecation data', async () => { @@ -72,8 +69,12 @@ describe('Kibana deprecations table', () => { it('shows critical and warning deprecations count', () => { const { find } = testBed; - expect(find('criticalDeprecationsCount').text()).toContain(criticalDeprecations.length); - expect(find('warningDeprecationsCount').text()).toContain(warningDeprecations.length); + expect(find('criticalDeprecationsCount').text()).toContain( + mockedCriticalKibanaDeprecations.length + ); + expect(find('warningDeprecationsCount').text()).toContain( + mockedWarningKibanaDeprecations.length + ); }); describe('Search bar', () => { @@ -83,12 +84,12 @@ describe('Kibana deprecations table', () => { // Show only critical deprecations await actions.searchBar.clickCriticalFilterButton(); const { rows: criticalRows } = table.getMetaData('kibanaDeprecationsTable'); - expect(criticalRows.length).toEqual(criticalDeprecations.length); + expect(criticalRows.length).toEqual(mockedCriticalKibanaDeprecations.length); // Show all deprecations await actions.searchBar.clickCriticalFilterButton(); const { rows: allRows } = table.getMetaData('kibanaDeprecationsTable'); - expect(allRows.length).toEqual(kibanaDeprecationsMockResponse.length); + expect(allRows.length).toEqual(mockedKibanaDeprecations.length); }); it('filters by type', async () => { @@ -99,7 +100,7 @@ describe('Kibana deprecations table', () => { const { rows: configRows } = table.getMetaData('kibanaDeprecationsTable'); - expect(configRows.length).toEqual(configDeprecations.length); + expect(configRows.length).toEqual(mockedConfigKibanaDeprecations.length); }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts index 6de1fd339f3cc..b45f0b0527ac0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts @@ -8,9 +8,8 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; -import { setupEnvironment } from '../helpers'; +import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../helpers'; import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; -import { kibanaDeprecationsMockResponse } from './mocked_responses'; describe('Error handling', () => { let testBed: KibanaTestBed; @@ -23,18 +22,21 @@ describe('Error handling', () => { test('handles plugin error', async () => { await act(async () => { - deprecationService.getAllDeprecations = jest.fn().mockReturnValue([ - ...kibanaDeprecationsMockResponse, - { - domainId: 'failed_plugin_id', - title: 'Failed to fetch deprecations for "failed_plugin_id"', - message: `Failed to get deprecations info for plugin "failed_plugin_id".`, - level: 'fetch_error', - correctiveActions: { - manualSteps: ['Check Kibana server logs for error message.'], + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ + deprecationService, + response: [ + ...kibanaDeprecationsServiceHelpers.defaultMockedResponses.mockedKibanaDeprecations, + { + domainId: 'failed_plugin_id', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: `Failed to get deprecations info for plugin "failed_plugin_id".`, + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, }, - }, - ]); + ], + }); testBed = await setupKibanaPage({ services: { @@ -57,9 +59,10 @@ describe('Error handling', () => { test('handles request error', async () => { await act(async () => { - deprecationService.getAllDeprecations = jest - .fn() - .mockRejectedValue(new Error('Internal Server Error')); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ + deprecationService, + mockRequestErrorMessage: 'Internal Server Error', + }); testBed = await setupKibanaPage({ services: { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts deleted file mode 100644 index 261fe719bf5bf..0000000000000 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/mocked_responses.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import type { DomainDeprecationDetails } from 'kibana/public'; - -export const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ - { - correctiveActions: { - manualSteps: ['Step 1', 'Step 2', 'Step 3'], - api: { - method: 'POST', - path: '/test', - }, - }, - domainId: 'test_domain_1', - level: 'critical', - title: 'Test deprecation title 1', - message: 'Test deprecation message 1', - deprecationType: 'config', - }, - { - correctiveActions: { - manualSteps: ['Step 1', 'Step 2', 'Step 3'], - }, - domainId: 'test_domain_2', - level: 'warning', - title: 'Test deprecation title 1', - message: 'Test deprecation message 2', - deprecationType: 'feature', - }, -]; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx index e39f0da488205..77d3862b9e962 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx @@ -8,22 +8,24 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; -import * as mockedResponses from './mocked_responses'; -import { setupEnvironment } from '../../helpers'; +import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../../helpers'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; +import { esDeprecations, esDeprecationsEmpty } from './mocked_responses'; describe('Overview - Fix deprecation issues step', () => { let testBed: OverviewTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); + const { + mockedCriticalKibanaDeprecations, + mockedWarningKibanaDeprecations, + } = kibanaDeprecationsServiceHelpers.defaultMockedResponses; beforeEach(async () => { - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(mockedResponses.esDeprecations); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecations); await act(async () => { const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockReturnValue(mockedResponses.kibanaDeprecations); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService }); testBed = await setupOverviewPage({ services: { @@ -52,7 +54,7 @@ describe('Overview - Fix deprecation issues step', () => { }); test(`Hides deprecation counts if it doesn't have any`, async () => { - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(mockedResponses.esDeprecationsEmpty); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecationsEmpty); await act(async () => { testBed = await setupOverviewPage(); @@ -166,14 +168,18 @@ describe('Overview - Fix deprecation issues step', () => { const { exists, find } = testBed; expect(exists('kibanaStatsPanel')).toBe(true); - expect(find('kibanaStatsPanel.warningDeprecations').text()).toContain('1'); - expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain('1'); + expect(find('kibanaStatsPanel.warningDeprecations').text()).toContain( + mockedWarningKibanaDeprecations.length + ); + expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain( + mockedCriticalKibanaDeprecations.length + ); }); test(`Hides deprecation count if it doesn't have any`, async () => { await act(async () => { const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest.fn().mockRejectedValue([]); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService, response: [] }); testBed = await setupOverviewPage({ services: { @@ -184,7 +190,9 @@ describe('Overview - Fix deprecation issues step', () => { }); }); - const { exists } = testBed; + const { exists, component } = testBed; + + component.update(); expect(exists('noDeprecationsLabel')).toBe(true); expect(exists('kibanaStatsPanel.warningDeprecations')).toBe(false); @@ -204,9 +212,10 @@ describe('Overview - Fix deprecation issues step', () => { test('Handles network failure', async () => { await act(async () => { const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest - .fn() - .mockRejectedValue(new Error('Internal Server Error')); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ + deprecationService, + mockRequestErrorMessage: 'Internal Server Error', + }); testBed = await setupOverviewPage({ services: { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts index 57373dbf07269..ece52b344cc22 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts @@ -5,7 +5,6 @@ * 2.0. */ -import type { DomainDeprecationDetails } from 'kibana/public'; import { ESUpgradeStatus } from '../../../../common/types'; export const esDeprecations: ESUpgradeStatus = { @@ -37,20 +36,3 @@ export const esDeprecationsEmpty: ESUpgradeStatus = { totalCriticalDeprecations: 0, deprecations: [], }; - -export const kibanaDeprecations: DomainDeprecationDetails[] = [ - { - title: 'mock-deprecation-title', - correctiveActions: { manualSteps: ['test-step'] }, - domainId: 'xpack.spaces', - level: 'critical', - message: 'Sample warning deprecation', - }, - { - title: 'mock-deprecation-title', - correctiveActions: { manualSteps: ['test-step'] }, - domainId: 'xpack.spaces', - level: 'warning', - message: 'Sample warning deprecation', - }, -]; From cb3de63bad46f7258e583434c863c2d7d7a830ca Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 8 Sep 2021 18:39:34 +0200 Subject: [PATCH 21/93] [Upgrade Assistant] Remove unnecessary EuiScreenReaderOnly from stat panels (#111518) * Remove EuiScreenReaderOnly implementations * Remove unused translations * Remove extra string after merge conflict --- .../translations/translations/ja-JP.json | 4 -- .../translations/translations/zh-CN.json | 6 --- .../fix_issues_step/es_stats/es_stats.tsx | 51 ++---------------- .../kibana_stats/kibana_stats.tsx | 53 ++----------------- 4 files changed, 6 insertions(+), 108 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 22d8d6d87db87..676446aa94100 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25220,10 +25220,7 @@ "xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.upgradeSnapshotErrorTitle": "スナップショットのアップグレードエラー", "xpack.upgradeAssistant.esDeprecations.pageDescription": "廃止予定のクラスターとインデックス設定をレビューします。アップグレード前に重要な問題を解決する必要があります。", "xpack.upgradeAssistant.esDeprecations.pageTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsLabel": "このクラスター{criticalDeprecations}には重大な廃止予定があります", "xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsTitle": "重大", - "xpack.upgradeAssistant.esDeprecationStats.loadingText": "Elasticsearchの廃止統計情報を読み込んでいます...", - "xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText": "警告なし。準備ができました。", "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "ドキュメント", @@ -25232,7 +25229,6 @@ "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibanaには{criticalDeprecations}個の重大な廃止予定があります", "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "重大", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "Kibana廃止予定の取得中にエラーが発生しました。", - "xpack.upgradeAssistant.kibanaDeprecationStats.loadingText": "Kibana廃止予定統計情報を読み込んでいます…", "xpack.upgradeAssistant.kibanaDeprecationStats.statsTitle": "Kibana", "xpack.upgradeAssistant.kibanaDeprecationStats.warningDeprecationsTitle": "警告", "xpack.upgradeAssistant.noDeprecationsPrompt.nextStepsDescription": "他のスタック廃止予定については、{overviewButton}を確認してください。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 41d986ef72400..10d395800dda3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25649,20 +25649,14 @@ "xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.upgradeSnapshotErrorTitle": "升级快照时出错", "xpack.upgradeAssistant.esDeprecations.pageDescription": "查看已弃用的群集和索引设置。在升级之前必须解决任何紧急问题。", "xpack.upgradeAssistant.esDeprecations.pageTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsLabel": "此集群具有 {criticalDeprecations} 个关键弃用", "xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsTitle": "紧急", - "xpack.upgradeAssistant.esDeprecationStats.loadingText": "正在加载 Elasticsearch 弃用统计……", - "xpack.upgradeAssistant.esDeprecationStats.noDeprecationsText": "无警告。已就绪!", "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "文档", "xpack.upgradeAssistant.kibanaDeprecations.loadingText": "正在加载弃用……", "xpack.upgradeAssistant.kibanaDeprecations.pageTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibana 具有 {criticalDeprecations} 个关键弃用", "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "紧急", - "xpack.upgradeAssistant.kibanaDeprecationStats.getWarningDeprecationsMessage": "Kibana 有 {warningDeprecations} 个警告{warningDeprecations, plural, other {弃用}}", "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "检索 Kibana 弃用时发生错误。", - "xpack.upgradeAssistant.kibanaDeprecationStats.loadingText": "正在加载 Kibana 弃用统计……", "xpack.upgradeAssistant.kibanaDeprecationStats.statsTitle": "Kibana", "xpack.upgradeAssistant.kibanaDeprecationStats.warningDeprecationsTitle": "警告", "xpack.upgradeAssistant.noDeprecationsPrompt.nextStepsDescription": "查看{overviewButton}以了解其他 Stack 弃用。", diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx index 9526f5bc2316c..a55f22c8dfda4 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx @@ -8,14 +8,7 @@ import React, { FunctionComponent } from 'react'; import { useHistory } from 'react-router-dom'; -import { - EuiStat, - EuiSpacer, - EuiFlexGroup, - EuiFlexItem, - EuiCard, - EuiScreenReaderOnly, -} from '@elastic/eui'; +import { EuiStat, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiCard } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; @@ -40,24 +33,6 @@ const i18nTexts = { defaultMessage: 'Critical', } ), - loadingText: i18n.translate('xpack.upgradeAssistant.esDeprecationStats.loadingText', { - defaultMessage: 'Loading Elasticsearch deprecation stats…', - }), - getCriticalDeprecationsMessage: (criticalDeprecations: number) => - i18n.translate('xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsLabel', { - defaultMessage: 'This cluster has {criticalDeprecations} critical deprecations', - values: { - criticalDeprecations, - }, - }), - getWarningDeprecationMessage: (warningDeprecations: number) => - i18n.translate('xpack.upgradeAssistant.esDeprecationStats.warningDeprecationsTooltip', { - defaultMessage: - 'This cluster has {warningDeprecations} non-critical {warningDeprecations, plural, one {deprecation} other {deprecations}}', - values: { - warningDeprecations, - }, - }), }; export const ESDeprecationStats: FunctionComponent = () => { @@ -107,17 +82,7 @@ export const ESDeprecationStats: FunctionComponent = () => { description={i18nTexts.criticalDeprecationsTitle} titleColor="danger" isLoading={isLoading} - > - {error === null && ( - -

- {isLoading - ? i18nTexts.loadingText - : i18nTexts.getCriticalDeprecationsMessage(criticalDeprecations.length)} -

-
- )} - + /> )} @@ -129,17 +94,7 @@ export const ESDeprecationStats: FunctionComponent = () => { titleElement="span" description={i18nTexts.warningDeprecationsTitle} isLoading={isLoading} - > - {!error && ( - -

- {isLoading - ? i18nTexts.loadingText - : i18nTexts.getWarningDeprecationMessage(warningDeprecations.length)} -

-
- )} - + /> )}
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx index 9388ee52f57a1..28e60e7e735fb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx @@ -8,15 +8,7 @@ import React, { FunctionComponent, useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { - EuiCard, - EuiStat, - EuiSpacer, - EuiFlexGroup, - EuiFlexItem, - EuiIconTip, - EuiScreenReaderOnly, -} from '@elastic/eui'; +import { EuiCard, EuiStat, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { DomainDeprecationDetails } from 'kibana/public'; @@ -47,25 +39,6 @@ const i18nTexts = { defaultMessage: 'An error occurred while retrieving Kibana deprecations.', } ), - loadingText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.loadingText', { - defaultMessage: 'Loading Kibana deprecation stats…', - }), - getCriticalDeprecationsMessage: (criticalDeprecations: number) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel', { - defaultMessage: - 'Kibana has {criticalDeprecations} critical {criticalDeprecations, plural, one {deprecation} other {deprecations}}', - values: { - criticalDeprecations, - }, - }), - getWarningDeprecationsMessage: (warningDeprecations: number) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.getWarningDeprecationsMessage', { - defaultMessage: - 'Kibana has {warningDeprecations} warning {warningDeprecations, plural, one {deprecation} other {deprecations}}', - values: { - warningDeprecations, - }, - }), }; export const KibanaDeprecationStats: FunctionComponent = () => { @@ -151,17 +124,7 @@ export const KibanaDeprecationStats: FunctionComponent = () => { description={i18nTexts.criticalDeprecationsTitle} titleColor="danger" isLoading={isLoading} - > - {error === undefined && ( - -

- {isLoading - ? i18nTexts.loadingText - : i18nTexts.getCriticalDeprecationsMessage(criticalDeprecationsCount)} -

-
- )} - + /> )} @@ -173,17 +136,7 @@ export const KibanaDeprecationStats: FunctionComponent = () => { titleElement="span" description={i18nTexts.warningDeprecationsTitle} isLoading={isLoading} - > - {!error && ( - -

- {isLoading - ? i18nTexts.loadingText - : i18nTexts.getWarningDeprecationsMessage(warningDeprecationsCount)} -

-
- )} - + /> )}
From 6bbe3e296b0a7b161f34055000cdcb8361206df7 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Wed, 8 Sep 2021 14:00:27 -0700 Subject: [PATCH 22/93] Use consistent 'issues' and 'critical' vs. 'warning' terminology in UA. (#111221) --- .../es_deprecations/deprecations_list.test.ts | 2 +- .../error_handling.test.ts | 6 ++++-- .../es_deprecations/es_deprecations.tsx | 4 ++-- .../es_deprecations/es_deprecations_table.tsx | 2 +- .../es_deprecations_table_cells.tsx | 8 +++++++- .../kibana_deprecations.tsx | 10 +++++----- .../kibana_deprecations_table.tsx | 19 +++++++++++++++---- 7 files changed, 35 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index 316e1a65f0890..390aeeb6d33e3 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -162,7 +162,7 @@ describe('ES deprecations table', () => { expect(exists('noDeprecationsRow')).toBe(true); expect(find('noDeprecationsRow').text()).toContain( - 'No Elasticsearch deprecation warnings found' + 'No Elasticsearch deprecation issues found' ); }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts index b45f0b0527ac0..dbe49dfb714b9 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts @@ -53,7 +53,7 @@ describe('Error handling', () => { expect(exists('kibanaDeprecationErrors')).toBe(true); expect(find('kibanaDeprecationErrors').text()).toContain( - 'Deprecation warnings may be incomplete' + 'List of deprecation issues might be incomplete' ); }); @@ -78,6 +78,8 @@ describe('Error handling', () => { component.update(); expect(exists('kibanaRequestError')).toBe(true); - expect(find('kibanaRequestError').text()).toContain('Could not retrieve Kibana deprecations'); + expect(find('kibanaRequestError').text()).toContain( + 'Could not retrieve Kibana deprecation issues' + ); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index b823740433f84..5ce37e2e43815 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -38,14 +38,14 @@ const getDeprecationCountByLevel = (deprecations: EnrichedDeprecationInfo[]) => const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.esDeprecations.pageTitle', { - defaultMessage: 'Elasticsearch deprecation warnings', + defaultMessage: 'Elasticsearch deprecation issues', }), pageDescription: i18n.translate('xpack.upgradeAssistant.esDeprecations.pageDescription', { defaultMessage: 'You must resolve all critical issues before upgrading. Back up recommended. Make sure you have a current snapshot before modifying your configuration or reindexing.', }), isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { - defaultMessage: 'Loading deprecations…', + defaultMessage: 'Loading deprecation issues…', }), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx index f1b693fa48f57..e37d8dc6f77fc 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx @@ -45,7 +45,7 @@ const i18nTexts = { noDeprecationsMessage: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.table.noDeprecationsMessage', { - defaultMessage: 'No Elasticsearch deprecation warnings found', + defaultMessage: 'No Elasticsearch deprecation issues found', } ), typeFilterLabel: i18n.translate('xpack.upgradeAssistant.esDeprecations.table.typeFilterLabel', { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx index a42ab1baa887f..2e2299ec8b1e0 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx @@ -26,6 +26,12 @@ const i18nTexts = { defaultMessage: 'Critical', } ), + warningBadgeLabel: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.defaultDeprecation.warningBadgeLabel', + { + defaultMessage: 'Warning', + } + ), manualCellLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.defaultDeprecation.manualCellLabel', { @@ -52,7 +58,7 @@ export const EsDeprecationsTableCells: React.FunctionComponent = ({ return {i18nTexts.criticalBadgeLabel}; } - return <>{''}; + return {i18nTexts.warningBadgeLabel}; } // "Issue" column diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index a6d7e4fdb674a..eec233b7fda6a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -26,7 +26,7 @@ const { useGlobalFlyout } = GlobalFlyout; const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { - defaultMessage: 'Kibana deprecation warnings', + defaultMessage: 'Kibana deprecation issues', }), pageDescription: ( i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.kibanaDeprecationErrorDescription', { defaultMessage: - 'Failed to get deprecation warnings for {pluginCount, plural, one {this plugin} other {these plugins}}: {pluginIds}. Check the Kibana server logs for more details.', + 'Failed to get deprecation issues for {pluginCount, plural, one {this plugin} other {these plugins}}: {pluginIds}. Check the Kibana server logs for more information.', values: { pluginCount: pluginIds.length, pluginIds: pluginIds.join(', '), }, }), requestErrorTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.requestErrorTitle', { - defaultMessage: 'Could not retrieve Kibana deprecations', + defaultMessage: 'Could not retrieve Kibana deprecation issues', }), requestErrorDescription: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecationErrors.requestErrorDescription', diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx index 9117bcdbcaee5..1df9402c686aa 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx @@ -86,6 +86,12 @@ const i18nTexts = { defaultMessage: 'critical', } ), + warningBadgeLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.warningBadgeLabel', + { + defaultMessage: 'warning', + } + ), searchPlaceholderLabel: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecations.table.searchPlaceholderLabel', { @@ -115,11 +121,16 @@ export const KibanaDeprecationsTable: React.FunctionComponent = ({ truncateText: true, sortable: true, render: (level: KibanaDeprecationDetails['level']) => { - if (level === 'critical') { - return {i18nTexts.criticalBadgeLabel}; - } + switch (level) { + case 'critical': + return {i18nTexts.criticalBadgeLabel}; - return <>{''}; + case 'warning': + return {i18nTexts.warningBadgeLabel}; + + default: + return <>{''}; + } }, }, { From 423dd9f9205d3bf390cea2adfab075b32788f41d Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Wed, 8 Sep 2021 16:32:52 -0700 Subject: [PATCH 23/93] Refactor UA Overview to support step-completion (#111243) * Refactor UA Overview to store step-completion state at the root and delegate step-completion logic to each step component. * Add completion status to logs and issues steps --- .../client_integration/helpers/index.ts | 1 + .../helpers/time_manipulation.ts | 24 ++++++++ .../overview/backup_step/backup_step.test.tsx | 58 ++++++++++++++----- .../fix_issues_step/fix_issues_step.test.tsx | 31 ++++++++++ .../fix_logs_step/fix_logs_step.test.tsx | 43 ++++++++++++-- .../overview/backup_step/backup_step.tsx | 19 +++--- .../overview/backup_step/cloud_backup.tsx | 35 ++++++++--- .../fix_issues_step/es_stats/es_stats.tsx | 27 +++++++-- .../fix_issues_step/fix_issues_step.tsx | 56 ++++++++++++++---- .../kibana_stats/kibana_stats.tsx | 12 +++- .../deprecations_count_checkpoint.tsx | 31 +++++++--- .../overview/fix_logs_step/fix_logs_step.tsx | 18 ++++-- .../components/overview/overview.tsx | 37 +++++++++--- .../public/application/components/types.ts | 5 ++ 14 files changed, 323 insertions(+), 74 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/time_manipulation.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts index 7b20b8f7504a2..8b8cadac70c48 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts @@ -6,4 +6,5 @@ */ export { setupEnvironment, WithAppDependencies, kibanaVersion } from './setup_environment'; +export { advanceTime } from './time_manipulation'; export { kibanaDeprecationsServiceHelpers } from './kibana_deprecations_service.mock'; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/time_manipulation.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/time_manipulation.ts new file mode 100644 index 0000000000000..65cec19549736 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/time_manipulation.ts @@ -0,0 +1,24 @@ +/* + * 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 { act } from 'react-dom/test-utils'; + +/** + * These helpers are intended to be used in conjunction with jest.useFakeTimers(). + */ + +const flushPromiseJobQueue = async () => { + // See https://stackoverflow.com/questions/52177631/jest-timer-and-promise-dont-work-well-settimeout-and-async-function + await Promise.resolve(); +}; + +export const advanceTime = async (ms: number) => { + await act(async () => { + jest.advanceTimersByTime(ms); + await flushPromiseJobQueue(); + }); +}; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx index 39a94ec458be4..3dcc55adbe61d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/backup_step/backup_step.test.tsx @@ -5,9 +5,8 @@ * 2.0. */ -import { act } from 'react-dom/test-utils'; - -import { setupEnvironment } from '../../helpers'; +import { CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS } from '../../../../common/constants'; +import { setupEnvironment, advanceTime } from '../../helpers'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; describe('Overview - Backup Step', () => { @@ -34,6 +33,11 @@ describe('Overview - Backup Step', () => { expect(exists('snapshotRestoreLink')).toBe(true); expect(find('snapshotRestoreLink').props().href).toBe('snapshotAndRestoreUrl'); }); + + test('renders step as incomplete ', () => { + const { exists } = testBed; + expect(exists('backupStep-incomplete')).toBe(true); + }); }); describe('On Cloud', () => { @@ -104,6 +108,11 @@ describe('Overview - Backup Step', () => { expect(exists('cloudSnapshotsLink')).toBe(true); expect(find('dataBackedUpStatus').text()).toContain('Last snapshot created on'); }); + + test('renders step as complete ', () => { + const { exists } = testBed; + expect(exists('backupStep-complete')).toBe(true); + }); }); describe(`when data isn't backed up`, () => { @@ -121,24 +130,47 @@ describe('Overview - Backup Step', () => { expect(exists('dataNotBackedUpStatus')).toBe(true); expect(exists('cloudSnapshotsLink')).toBe(true); }); + + test('renders step as incomplete ', () => { + const { exists } = testBed; + expect(exists('backupStep-incomplete')).toBe(true); + }); }); + }); - // FLAKY: https://github.com/elastic/kibana/issues/111255 - test.skip('polls for new status', async () => { - // The behavior we're testing involves state changes over time, so we need finer control over - // timing. + describe('poll for new status', () => { + beforeEach(async () => { jest.useFakeTimers(); - testBed = await setupCloudOverviewPage(); - expect(server.requests.length).toBe(4); - // Resolve the polling timeout. - await act(async () => { - jest.runAllTimers(); + // First request will succeed. + httpRequestsMockHelpers.setLoadCloudBackupStatusResponse({ + isBackedUp: true, + lastBackupTime: '2021-08-25T19:59:59.863Z', }); - expect(server.requests.length).toBe(5); + testBed = await setupCloudOverviewPage(); + }); + + afterEach(() => { jest.useRealTimers(); }); + + test('renders step as incomplete when a success state is followed by an error state', async () => { + const { exists } = testBed; + expect(exists('backupStep-complete')).toBe(true); + + // Second request will error. + httpRequestsMockHelpers.setLoadCloudBackupStatusResponse(undefined, { + statusCode: 400, + message: 'error', + }); + + // Resolve the polling timeout. + await advanceTime(CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS); + testBed.component.update(); + + expect(exists('backupStep-incomplete')).toBe(true); + }); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx index 77d3862b9e962..0b572ab41deaa 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx @@ -44,6 +44,37 @@ describe('Overview - Fix deprecation issues step', () => { server.restore(); }); + describe('Step status', () => { + test(`It's complete when there are no critical deprecations`, async () => { + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecationsEmpty); + + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + deprecationService.getAllDeprecations = jest.fn().mockRejectedValue([]); + + testBed = await setupOverviewPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { exists, component } = testBed; + + component.update(); + + expect(exists(`fixIssuesStep-complete`)).toBe(true); + }); + + test(`It's incomplete when there are critical deprecations`, async () => { + const { exists } = testBed; + + expect(exists(`fixIssuesStep-incomplete`)).toBe(true); + }); + }); + describe('ES deprecations', () => { test('Shows deprecation warning and critical counts', () => { const { exists, find } = testBed; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index dec34ba1e3720..acc64e2872642 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -33,14 +33,49 @@ describe('Overview - Fix deprecation logs step', () => { server.restore(); }); + describe('Step status', () => { + test(`It's complete when there are no deprecation logs since last checkpoint`, async () => { + httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse(getLoggingResponse(true)); + + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 0, + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, component } = testBed; + + component.update(); + + expect(exists(`fixLogsStep-complete`)).toBe(true); + }); + + test(`It's incomplete when there are deprecation logs since last checkpoint`, async () => { + httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse(getLoggingResponse(true)); + + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 5, + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, component } = testBed; + + component.update(); + + expect(exists(`fixLogsStep-incomplete`)).toBe(true); + }); + }); + describe('Step 1 - Toggle log writing and collecting', () => { test('toggles deprecation logging', async () => { const { find, actions } = testBed; - httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse({ - isDeprecationLogIndexingEnabled: false, - isDeprecationLoggingEnabled: false, - }); + httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse(getLoggingResponse(false)); expect(find('deprecationLoggingToggle').props()['aria-checked']).toBe(true); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx index b85f166e413f5..46b11aee15b33 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/backup_step.tsx @@ -11,33 +11,34 @@ import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import type { CloudSetup } from '../../../../../../cloud/public'; import { OnPremBackup } from './on_prem_backup'; -import { CloudBackup, CloudBackupStatusResponse } from './cloud_backup'; +import { CloudBackup } from './cloud_backup'; +import type { OverviewStepProps } from '../../types'; const title = i18n.translate('xpack.upgradeAssistant.overview.backupStepTitle', { defaultMessage: 'Back up your data', }); -interface Props { +interface Props extends OverviewStepProps { cloud?: CloudSetup; - cloudBackupStatusResponse?: CloudBackupStatusResponse; } -export const getBackupStep = ({ cloud, cloudBackupStatusResponse }: Props): EuiStepProps => { +export const getBackupStep = ({ cloud, isComplete, setIsComplete }: Props): EuiStepProps => { + const status = isComplete ? 'complete' : 'incomplete'; + if (cloud?.isCloudEnabled) { return { + status, title, - status: cloudBackupStatusResponse!.data?.isBackedUp ? 'complete' : 'incomplete', + 'data-test-subj': `backupStep-${status}`, children: ( - + ), }; } return { title, + 'data-test-subj': 'backupStep-incomplete', status: 'incomplete', children: , }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx index e73cfaab8b2b6..abef34a27f30f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import moment from 'moment-timezone'; import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -20,22 +20,39 @@ import { EuiCallOut, } from '@elastic/eui'; -import { CloudBackupStatus } from '../../../../../common/types'; -import { UseRequestResponse } from '../../../../shared_imports'; -import { ResponseError } from '../../../lib/api'; - -export type CloudBackupStatusResponse = UseRequestResponse; +import { useAppContext } from '../../../app_context'; interface Props { - cloudBackupStatusResponse: UseRequestResponse; cloudSnapshotsUrl: string; + setIsComplete: (isComplete: boolean) => void; } export const CloudBackup: React.FunctionComponent = ({ - cloudBackupStatusResponse, cloudSnapshotsUrl, + setIsComplete, }) => { - const { isInitialRequest, isLoading, error, data, resendRequest } = cloudBackupStatusResponse; + const { + services: { api }, + } = useAppContext(); + + const { + isInitialRequest, + isLoading, + error, + data, + resendRequest, + } = api.useLoadCloudBackupStatus(); + + // Tell overview whether the step is complete or not. + useEffect(() => { + // Loading shouldn't invalidate the previous state. + if (!isLoading) { + // An error should invalidate the previous state. + setIsComplete((!error && data?.isBackedUp) ?? false); + } + // Depending upon setIsComplete would create an infinite loop. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [error, isLoading, data]); if (isInitialRequest && isLoading) { return ; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx index a55f22c8dfda4..7d0dcacfaa207 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useEffect, useMemo } from 'react'; import { useHistory } from 'react-router-dom'; import { EuiStat, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiCard } from '@elastic/eui'; @@ -35,7 +35,11 @@ const i18nTexts = { ), }; -export const ESDeprecationStats: FunctionComponent = () => { +interface Props { + setIsFixed: (isFixed: boolean) => void; +} + +export const ESDeprecationStats: FunctionComponent = ({ setIsFixed }) => { const history = useHistory(); const { services: { api }, @@ -43,10 +47,21 @@ export const ESDeprecationStats: FunctionComponent = () => { const { data: esDeprecations, isLoading, error } = api.useLoadEsDeprecations(); - const warningDeprecations = - esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical === false) || []; - const criticalDeprecations = - esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical) || []; + const warningDeprecations = useMemo( + () => + esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical === false) || [], + [esDeprecations] + ); + const criticalDeprecations = useMemo( + () => esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical) || [], + [esDeprecations] + ); + + useEffect(() => { + if (!isLoading && !error) { + setIsFixed(criticalDeprecations.length === 0); + } + }, [setIsFixed, criticalDeprecations, isLoading, error]); const hasWarnings = warningDeprecations.length > 0; const hasCritical = criticalDeprecations.length > 0; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx index f235075350e66..df9bf58198d9d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { FunctionComponent, useState, useEffect } from 'react'; import { EuiText, EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -13,6 +13,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import { ESDeprecationStats } from './es_stats'; import { KibanaDeprecationStats } from './kibana_stats'; +import type { OverviewStepProps } from '../../types'; import './_fix_issues_step.scss'; @@ -22,10 +23,49 @@ const i18nTexts = { }), }; -export const getFixIssuesStep = ({ nextMajor }: { nextMajor: number }): EuiStepProps => { +interface Props { + setIsComplete: OverviewStepProps['setIsComplete']; +} + +interface StepProps extends OverviewStepProps { + nextMajor: number; +} + +const FixIssuesStep: FunctionComponent = ({ setIsComplete }) => { + // We consider ES and Kibana issues to be fixed when there are 0 critical issues. + const [isEsFixed, setIsEsFixed] = useState(false); + const [isKibanaFixed, setIsKibanaFixed] = useState(false); + + useEffect(() => { + setIsComplete(isEsFixed && isKibanaFixed); + // Depending upon setIsComplete would create an infinite loop. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isEsFixed, isKibanaFixed]); + + return ( + + + + + + + + + + ); +}; + +export const getFixIssuesStep = ({ + nextMajor, + isComplete, + setIsComplete, +}: StepProps): EuiStepProps => { + const status = isComplete ? 'complete' : 'incomplete'; + return { title: i18nTexts.reviewStepTitle, - status: 'incomplete', + status, + 'data-test-subj': `fixIssuesStep-${status}`, children: ( <> @@ -40,15 +80,7 @@ export const getFixIssuesStep = ({ nextMajor }: { nextMajor: number }): EuiStepP - - - - - - - - - + ), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx index 28e60e7e735fb..2cfc555116ba6 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx @@ -41,7 +41,11 @@ const i18nTexts = { ), }; -export const KibanaDeprecationStats: FunctionComponent = () => { +interface Props { + setIsFixed: (isFixed: boolean) => void; +} + +export const KibanaDeprecationStats: FunctionComponent = ({ setIsFixed }) => { const history = useHistory(); const { services: { @@ -77,6 +81,12 @@ export const KibanaDeprecationStats: FunctionComponent = () => { const criticalDeprecationsCount = kibanaDeprecations?.filter((deprecation) => deprecation.level === 'critical')?.length ?? 0; + useEffect(() => { + if (!isLoading && !error) { + setIsFixed(criticalDeprecationsCount === 0); + } + }, [setIsFixed, criticalDeprecationsCount, isLoading, error]); + const hasCritical = criticalDeprecationsCount > 0; const hasWarnings = warningDeprecationsCount > 0; const hasNoDeprecations = !isLoading && !error && !hasWarnings && !hasCritical; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx index 58b7b7ca11ebd..f0a4096687f6c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent, useState } from 'react'; +import React, { FunctionComponent, useState, useEffect } from 'react'; import moment from 'moment-timezone'; import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; @@ -64,7 +64,13 @@ const getPreviousCheckpointDate = () => { return now; }; -export const DeprecationsCountCheckpoint: FunctionComponent = () => { +interface Props { + setHasNoDeprecationLogs: (hasNoLogs: boolean) => void; +} + +export const DeprecationsCountCheckpoint: FunctionComponent = ({ + setHasNoDeprecationLogs, +}) => { const { services: { api }, } = useAppContext(); @@ -73,10 +79,11 @@ export const DeprecationsCountCheckpoint: FunctionComponent = () => { previousCheck ); - const warningsCount = data?.count || 0; - const calloutTint = warningsCount > 0 ? 'warning' : 'success'; - const calloutIcon = warningsCount > 0 ? 'alert' : 'check'; - const calloutTestId = warningsCount > 0 ? 'hasWarningsCallout' : 'noWarningsCallout'; + const logsCount = data?.count || 0; + const hasLogs = logsCount > 0; + const calloutTint = hasLogs ? 'warning' : 'success'; + const calloutIcon = hasLogs ? 'alert' : 'check'; + const calloutTestId = hasLogs ? 'hasWarningsCallout' : 'noWarningsCallout'; const onResetClick = () => { const now = moment().toISOString(); @@ -85,6 +92,16 @@ export const DeprecationsCountCheckpoint: FunctionComponent = () => { localStorage.set(LS_SETTING_ID, now); }; + useEffect(() => { + // Loading shouldn't invalidate the previous state. + if (!isLoading) { + // An error should invalidate the previous state. + setHasNoDeprecationLogs(!error && !hasLogs); + } + // Depending upon setHasNoDeprecationLogs would create an infinite loop. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [error, isLoading, hasLogs]); + if (isInitialRequest && isLoading) { return ; } @@ -109,7 +126,7 @@ export const DeprecationsCountCheckpoint: FunctionComponent = () => { return ( { +interface Props { + setIsComplete: OverviewStepProps['setIsComplete']; +} + +const FixLogsStep: FunctionComponent = ({ setIsComplete }) => { const state = useDeprecationLogging(); return ( @@ -88,17 +93,20 @@ const FixLogsStep: FunctionComponent = () => {

{i18nTexts.deprecationsCountCheckpointTitle}

- + )} ); }; -export const getFixLogsStep = (): EuiStepProps => { +export const getFixLogsStep = ({ isComplete, setIsComplete }: OverviewStepProps): EuiStepProps => { + const status = isComplete ? 'complete' : 'incomplete'; + return { + status, title: i18nTexts.identifyStepTitle, - status: 'incomplete', - children: , + 'data-test-subj': `fixLogsStep-${status}`, + children: , }; }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index 1c11bc165d931..010c9b7367158 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent, useEffect } from 'react'; +import React, { FunctionComponent, useEffect, useState } from 'react'; import { EuiSteps, @@ -26,6 +26,8 @@ import { getFixIssuesStep } from './fix_issues_step'; import { getFixLogsStep } from './fix_logs_step'; import { getUpgradeStep } from './upgrade_step'; +type OverviewStep = 'backup' | 'fix_issues' | 'fix_logs'; + export const Overview: FunctionComponent = () => { const { kibanaVersionInfo: { nextMajor }, @@ -51,11 +53,19 @@ export const Overview: FunctionComponent = () => { breadcrumbs.setBreadcrumbs('overview'); }, [breadcrumbs]); - let cloudBackupStatusResponse; + const [completedStepsMap, setCompletedStepsMap] = useState({ + backup: false, + fix_issues: false, + fix_logs: false, + }); - if (cloud?.isCloudEnabled) { - cloudBackupStatusResponse = api.useLoadCloudBackupStatus(); - } + const isStepComplete = (step: OverviewStep) => completedStepsMap[step]; + const setCompletedStep = (step: OverviewStep, isCompleted: boolean) => { + setCompletedStepsMap({ + ...completedStepsMap, + [step]: isCompleted, + }); + }; return ( @@ -97,9 +107,20 @@ export const Overview: FunctionComponent = () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts index 81495c45420bf..6b52f7cece514 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts @@ -31,3 +31,8 @@ export interface DeprecationLoggingPreviewProps { resendRequest: () => void; toggleLogging: () => void; } + +export interface OverviewStepProps { + isComplete: boolean; + setIsComplete: (isComplete: boolean) => void; +} From bbb3afab32972859f97320ecfe26f119ffdb3b67 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 9 Sep 2021 13:38:13 +0200 Subject: [PATCH 24/93] [Upgrade Assistant] External links with checkpoint time-range applied (#111252) * Bound query around last checkpoint date * Fix tests * Also test discover url contains search params * Small refactor * Keep state about lastCheckpoint in parent component * Remove space * Address CR changes Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../helpers/app_context.mock.ts | 19 +++++++--- .../fix_logs_step/fix_logs_step.test.tsx | 23 ++++++++++-- .../deprecations_count_checkpoint.tsx | 32 +++++------------ .../overview/fix_logs_step/external_links.tsx | 36 ++++++++++++------- .../overview/fix_logs_step/fix_logs_step.tsx | 16 +++++++-- .../public/application/lib/logs_checkpoint.ts | 30 ++++++++++++++++ .../upgrade_assistant/public/plugin.ts | 3 +- .../plugins/upgrade_assistant/public/types.ts | 3 -- .../plugins/upgrade_assistant/tsconfig.json | 1 + 9 files changed, 113 insertions(+), 50 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/lib/logs_checkpoint.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index 7550055d8242d..42c05c2d80d37 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -33,13 +33,24 @@ const idToUrlMap = { SNAPSHOT_RESTORE_LOCATOR: 'snapshotAndRestoreUrl', DISCOVER_APP_LOCATOR: 'discoverUrl', }; +type IdKey = keyof typeof idToUrlMap; + +const stringifySearchParams = (params: Record) => { + const stringifiedParams = Object.keys(params).reduce((list, key) => { + const value = typeof params[key] === 'object' ? JSON.stringify(params[key]) : params[key]; + + return { ...list, [key]: value }; + }, {}); + + return new URLSearchParams(stringifiedParams).toString(); +}; const shareMock = sharePluginMock.createSetupContract(); -shareMock.url.locators.get = (id) => ({ - // @ts-expect-error This object is missing some properties that we're not using in the UI +// @ts-expect-error This object is missing some properties that we're not using in the UI +shareMock.url.locators.get = (id: IdKey) => ({ useUrl: (): string | undefined => idToUrlMap[id], - // @ts-expect-error This object is missing some properties that we're not using in the UI - getUrl: (): string | undefined => idToUrlMap[id], + getUrl: (params: Record): string | undefined => + `${idToUrlMap[id]}?${stringifySearchParams(params)}`, }); export const getAppContextMock = () => ({ diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index acc64e2872642..e19ea5b1dfd99 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -7,6 +7,20 @@ import { act } from 'react-dom/test-utils'; +// Once the logs team register the kibana locators in their app, we should be able +// to remove this mock and follow a similar approach to how discover link is tested. +// See: https://github.com/elastic/kibana/issues/104855 +const MOCKED_TIME = '2021-09-05T10:49:01.805Z'; +jest.mock('../../../../public/application/lib/logs_checkpoint', () => { + const originalModule = jest.requireActual('../../../../public/application/lib/logs_checkpoint'); + + return { + __esModule: true, + ...originalModule, + loadLogsCheckpoint: jest.fn().mockReturnValue('2021-09-05T10:49:01.805Z'), + }; +}); + import { DeprecationLoggingStatus } from '../../../../common/types'; import { DEPRECATION_LOGS_SOURCE_ID } from '../../../../common/constants'; import { setupEnvironment } from '../../helpers'; @@ -180,7 +194,7 @@ describe('Overview - Fix deprecation logs step', () => { expect(exists('viewObserveLogs')).toBe(true); expect(find('viewObserveLogs').props().href).toBe( - `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}` + `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}&logPosition=(end:now,start:'${MOCKED_TIME}')` ); }); @@ -194,7 +208,12 @@ describe('Overview - Fix deprecation logs step', () => { component.update(); expect(exists('viewDiscoverLogs')).toBe(true); - expect(find('viewDiscoverLogs').props().href).toBe('discoverUrl'); + + const decodedUrl = decodeURIComponent(find('viewDiscoverLogs').props().href); + expect(decodedUrl).toContain('discoverUrl'); + ['"language":"kuery"', '"query":"@timestamp+>'].forEach((param) => { + expect(decodedUrl).toContain(param); + }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx index f0a4096687f6c..244583e9154c1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -5,17 +5,13 @@ * 2.0. */ -import React, { FunctionComponent, useState, useEffect } from 'react'; +import React, { FunctionComponent, useEffect } from 'react'; import moment from 'moment-timezone'; import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { EuiCallOut, EuiButton, EuiLoadingContent } from '@elastic/eui'; import { useAppContext } from '../../../../app_context'; -import { Storage } from '../../../../../shared_imports'; - -const LS_SETTING_ID = 'kibana.upgradeAssistant.lastCheckpoint'; -const localStorage = new Storage(window.localStorage); const i18nTexts = { calloutTitle: (warningsCount: number, previousCheck: string) => ( @@ -51,32 +47,22 @@ const i18nTexts = { ), }; -const getPreviousCheckpointDate = () => { - const storedValue = moment(localStorage.get(LS_SETTING_ID)); - - if (storedValue.isValid()) { - return storedValue.toISOString(); - } - - const now = moment().toISOString(); - localStorage.set(LS_SETTING_ID, now); - - return now; -}; - interface Props { + checkpoint: string; + setCheckpoint: (value: string) => void; setHasNoDeprecationLogs: (hasNoLogs: boolean) => void; } export const DeprecationsCountCheckpoint: FunctionComponent = ({ + checkpoint, + setCheckpoint, setHasNoDeprecationLogs, }) => { const { services: { api }, } = useAppContext(); - const [previousCheck, setPreviousCheck] = useState(getPreviousCheckpointDate()); const { data, error, isLoading, resendRequest, isInitialRequest } = api.getDeprecationLogsCount( - previousCheck + checkpoint ); const logsCount = data?.count || 0; @@ -87,9 +73,7 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ const onResetClick = () => { const now = moment().toISOString(); - - setPreviousCheck(now); - localStorage.set(LS_SETTING_ID, now); + setCheckpoint(now); }; useEffect(() => { @@ -126,7 +110,7 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ return ( { - const { indexPatterns: indexPatternService } = dataService; +interface Props { + checkpoint: string; +} - const results = await indexPatternService.find(DEPRECATION_LOGS_INDEX_PATTERN); +const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) => { + const results = await dataService.dataViews.find(DEPRECATION_LOGS_INDEX_PATTERN); // Since the find might return also results with wildcard matchers we need to find the // index pattern that has an exact match with our title. const deprecationIndexPattern = results.find( @@ -30,7 +33,7 @@ const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) if (deprecationIndexPattern) { return deprecationIndexPattern.id; } else { - const newIndexPattern = await indexPatternService.createAndSave({ + const newIndexPattern = await dataService.dataViews.createAndSave({ title: DEPRECATION_LOGS_INDEX_PATTERN, allowNoIndex: true, }); @@ -38,7 +41,7 @@ const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) } }; -const DiscoverAppLink: FunctionComponent = () => { +const DiscoverAppLink: FunctionComponent = ({ checkpoint }) => { const { services: { data: dataService }, plugins: { share }, @@ -55,12 +58,19 @@ const DiscoverAppLink: FunctionComponent = () => { return; } - const url = await locator.getUrl({ indexPatternId }); + const url = await locator.getUrl({ + indexPatternId, + query: { + language: 'kuery', + query: `@timestamp > "${checkpoint}"`, + }, + }); + setDiscoveryUrl(url); }; getDiscoveryUrl(); - }, [dataService, share.url.locators]); + }, [dataService, checkpoint, share.url.locators]); return ( @@ -72,14 +82,16 @@ const DiscoverAppLink: FunctionComponent = () => { ); }; -const ObservabilityAppLink: FunctionComponent = () => { +const ObservabilityAppLink: FunctionComponent = ({ checkpoint }) => { const { services: { core: { http }, }, } = useAppContext(); const logStreamUrl = http?.basePath?.prepend( - `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}` + `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}&logPosition=(end:now,start:${encode( + checkpoint + )})` ); return ( @@ -92,7 +104,7 @@ const ObservabilityAppLink: FunctionComponent = () => { ); }; -export const ExternalLinks: FunctionComponent = () => { +export const ExternalLinks: FunctionComponent = ({ checkpoint }) => { return ( @@ -106,7 +118,7 @@ export const ExternalLinks: FunctionComponent = () => {

- +
@@ -120,7 +132,7 @@ export const ExternalLinks: FunctionComponent = () => {

- +
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index 189dc4e39c0b2..c0977847d121c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiText, EuiSpacer, EuiPanel, EuiCallOut } from '@elastic/eui'; @@ -15,6 +15,7 @@ import { ExternalLinks } from './external_links'; import { DeprecationsCountCheckpoint } from './deprecations_count_checkpoint'; import { useDeprecationLogging } from './use_deprecation_logging'; import { DeprecationLoggingToggle } from './deprecation_logging_toggle'; +import { loadLogsCheckpoint, saveLogsCheckpoint } from '../../../lib/logs_checkpoint'; import type { OverviewStepProps } from '../../types'; const i18nTexts = { @@ -54,6 +55,11 @@ interface Props { const FixLogsStep: FunctionComponent = ({ setIsComplete }) => { const state = useDeprecationLogging(); + const [checkpoint, setCheckpoint] = useState(loadLogsCheckpoint()); + + useEffect(() => { + saveLogsCheckpoint(checkpoint); + }, [checkpoint]); return ( <> @@ -86,14 +92,18 @@ const FixLogsStep: FunctionComponent = ({ setIsComplete }) => {

{i18nTexts.analyzeTitle}

- +

{i18nTexts.deprecationsCountCheckpointTitle}

- + )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/logs_checkpoint.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/logs_checkpoint.ts new file mode 100644 index 0000000000000..59c3adaed95df --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/logs_checkpoint.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment-timezone'; + +import { Storage } from '../../shared_imports'; + +const SETTING_ID = 'kibana.upgradeAssistant.lastCheckpoint'; +const localStorage = new Storage(window.localStorage); + +export const loadLogsCheckpoint = () => { + const storedValue = moment(localStorage.get(SETTING_ID)); + + if (storedValue.isValid()) { + return storedValue.toISOString(); + } + + const now = moment().toISOString(); + localStorage.set(SETTING_ID, now); + + return now; +}; + +export const saveLogsCheckpoint = (value: string) => { + localStorage.set(SETTING_ID, value); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index 2385bbe8b33fb..24a9d75a7508b 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -43,7 +43,7 @@ export class UpgradeAssistantUIPlugin title: pluginName, order: 1, async mount(params) { - const [coreStart, { discover, data }] = await coreSetup.getStartServices(); + const [coreStart, { data }] = await coreSetup.getStartServices(); const { chrome: { docTitle }, @@ -62,7 +62,6 @@ export class UpgradeAssistantUIPlugin core: coreStart, data, history: params.history, - discover, api: apiService, breadcrumbs: breadcrumbService, }, diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index 8b5ac002c25ac..55c43e452a864 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -6,7 +6,6 @@ */ import { ScopedHistory } from 'kibana/public'; -import { DiscoverStart } from 'src/plugins/discover/public'; import { ManagementSetup } from 'src/plugins/management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SharePluginSetup } from 'src/plugins/share/public'; @@ -30,7 +29,6 @@ export interface SetupDependencies { export interface StartDependencies { licensing: LicensingPluginStart; - discover: DiscoverStart; data: DataPublicPluginStart; } @@ -50,7 +48,6 @@ export interface AppDependencies { }; services: { core: CoreStart; - discover: DiscoverStart; data: DataPublicPluginStart; breadcrumbs: BreadcrumbService; history: ScopedHistory; diff --git a/x-pack/plugins/upgrade_assistant/tsconfig.json b/x-pack/plugins/upgrade_assistant/tsconfig.json index 39d7404ebea9d..4336acb77c2eb 100644 --- a/x-pack/plugins/upgrade_assistant/tsconfig.json +++ b/x-pack/plugins/upgrade_assistant/tsconfig.json @@ -7,6 +7,7 @@ "declarationMap": true }, "include": [ + "../../../typings/**/*", "__jest__/**/*", "common/**/*", "public/**/*", From 54c295d76e06077ac68eb0b92e043224e47bbc09 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 9 Sep 2021 16:36:41 +0200 Subject: [PATCH 25/93] [Upgrade Assistant] Tests for updating step state accordingly if API poll receives count followed by error (#111701) * Add test for logs count polling * Test when count api fails --- .../fix_logs_step/fix_logs_step.test.tsx | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index e19ea5b1dfd99..b9a46ce62e20d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -23,8 +23,9 @@ jest.mock('../../../../public/application/lib/logs_checkpoint', () => { import { DeprecationLoggingStatus } from '../../../../common/types'; import { DEPRECATION_LOGS_SOURCE_ID } from '../../../../common/constants'; -import { setupEnvironment } from '../../helpers'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; +import { setupEnvironment, advanceTime } from '../../helpers'; +import { DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS } from '../../../../common/constants'; const getLoggingResponse = (toggle: boolean): DeprecationLoggingStatus => ({ isDeprecationLogIndexingEnabled: toggle, @@ -308,5 +309,42 @@ describe('Overview - Fix deprecation logs step', () => { expect(exists('noWarningsCallout')).toBe(true); }); + + describe('Poll for logs count', () => { + beforeEach(async () => { + jest.useFakeTimers(); + + // First request should make the step be complete + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ + count: 0, + }); + + testBed = await setupOverviewPage(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + test('renders step as incomplete when a success state is followed by an error state', async () => { + const { exists } = testBed; + + expect(exists('fixLogsStep-complete')).toBe(true); + + // second request will error + const error = { + statusCode: 500, + error: 'Internal server error', + message: 'Internal server error', + }; + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse(undefined, error); + + // Resolve the polling timeout. + await advanceTime(DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS); + testBed.component.update(); + + expect(exists('fixLogsStep-incomplete')).toBe(true); + }); + }); }); }); From 358182693a0892a41814f46a5c82f08accecb0ca Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 9 Sep 2021 15:12:15 -0400 Subject: [PATCH 26/93] [Upgrade Assistant] Add a11y tests for es deprecation flyouts (#110843) --- .../deprecation_types/default/flyout.tsx | 6 +- .../index_settings/flyout.tsx | 2 +- .../deprecation_types/ml_snapshots/flyout.tsx | 2 +- .../reindex/flyout/container.tsx | 2 +- .../accessibility/apps/upgrade_assistant.ts | 86 +++++++++++++++---- .../page_objects/upgrade_assistant_page.ts | 13 +++ 6 files changed, 88 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx index 439062e027650..9262ea9664033 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx @@ -62,7 +62,9 @@ export const DefaultDeprecationFlyout = ({ <> -

{message}

+

+ {message} +

{index && ( @@ -74,7 +76,7 @@ export const DefaultDeprecationFlyout = ({
-

{details}

+

{details}

{i18nTexts.learnMoreLinkLabel} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx index 1567562db53ee..edb46ee0dc85b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx @@ -110,7 +110,7 @@ export const RemoveIndexSettingsFlyout = ({ <> -

{message}

+

{message}

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index 5d61b076119e7..a972b7ec192d2 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -169,7 +169,7 @@ export const FixSnapshotsFlyout = ({ <> -

{i18nTexts.flyoutTitle}

+

{i18nTexts.flyoutTitle}

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx index 23008a4f2f1b8..d2d07b47acd49 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx @@ -131,7 +131,7 @@ export const ReindexFlyout: React.FunctionComponent = ({ <> -

+

{ await PageObjects.upgradeAssistant.navigateToPage(); try { - // Create an index that will trigger a deprecation warning to test the ES deprecations page + // Create two indices that will trigger deprecation warnings to test the ES deprecations page + await es.indices.create(multiFieldsIndexDeprecation); await es.indices.create(translogSettingsIndexDeprecation); } catch (e) { - log.debug('[Setup error] Error creating index'); + log.debug('[Setup error] Error creating indices'); throw e; } }); @@ -42,10 +68,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async () => { try { await es.indices.delete({ - index: [translogSettingsIndexDeprecation.index], + index: [multiFieldsIndexDeprecation.index, translogSettingsIndexDeprecation.index], }); } catch (e) { - log.debug('[Cleanup error] Error deleting index'); + log.debug('[Cleanup error] Error deleting indices'); throw e; } }); @@ -57,22 +83,46 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - it('Elasticsearch deprecations page', async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/es_deprecations', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); - - await retry.waitFor('Elasticsearch deprecations table to be visible', async () => { - return testSubjects.exists('esDeprecationsTable'); + describe('Elasticsearch deprecations page', () => { + beforeEach(async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/es_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); + + await retry.waitFor('Elasticsearch deprecations table to be visible', async () => { + return testSubjects.exists('esDeprecationsTable'); + }); }); - await a11y.testAppSnapshot(); + it('Deprecations table', async () => { + await a11y.testAppSnapshot(); + }); + + it('Index settings deprecation flyout', async () => { + await PageObjects.upgradeAssistant.clickEsDeprecation( + 'indexSettings' // An index setting deprecation was added in the before() hook so should be guaranteed + ); + await retry.waitFor('ES index settings deprecation flyout to be visible', async () => { + return testSubjects.exists('indexSettingsDetails'); + }); + await a11y.testAppSnapshot(); + }); + + it('Default deprecation flyout', async () => { + await PageObjects.upgradeAssistant.clickEsDeprecation( + 'default' // A default deprecation was added in the before() hook so should be guaranteed + ); + await retry.waitFor('ES default deprecation flyout to be visible', async () => { + return testSubjects.exists('defaultDeprecationDetails'); + }); + await a11y.testAppSnapshot(); + }); }); describe('Kibana deprecations page', () => { diff --git a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts index 406800d775417..e763145a715ff 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts +++ b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts @@ -57,4 +57,17 @@ export class UpgradeAssistantPageObject extends FtrService { this.log.debug('Unable to find selected deprecation row'); } } + + async clickEsDeprecation(deprecationType: 'indexSettings' | 'default' | 'reindex' | 'ml') { + const table = await this.testSubjects.find('esDeprecationsTable'); + const deprecationIssueLink = await ( + await table.findByTestSubject(`${deprecationType}TableCell-message`) + ).findByCssSelector('button'); + + if (deprecationIssueLink) { + await deprecationIssueLink.click(); + } else { + this.log.debug('Unable to find selected deprecation'); + } + } } From ed5e6e574c7828fb2c0986a283572bcbb0c74293 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Fri, 10 Sep 2021 16:07:06 +0200 Subject: [PATCH 27/93] [Upgrade Assistant] Set fix_logs step as incomplete if log collection is not enabled (#111827) * set step as incomplete if toggle is disabled * Fix test names * Remove unnecessary mocks --- .../fix_logs_step/fix_logs_step.test.tsx | 30 +++++++++++++------ .../overview/fix_logs_step/fix_logs_step.tsx | 9 ++++++ .../public/shared_imports.ts | 2 -- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index b9a46ce62e20d..c81e0b2bd943e 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -50,11 +50,7 @@ describe('Overview - Fix deprecation logs step', () => { describe('Step status', () => { test(`It's complete when there are no deprecation logs since last checkpoint`, async () => { - httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse(getLoggingResponse(true)); - - httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ - count: 0, - }); + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ count: 0 }); await act(async () => { testBed = await setupOverviewPage(); @@ -68,20 +64,36 @@ describe('Overview - Fix deprecation logs step', () => { }); test(`It's incomplete when there are deprecation logs since last checkpoint`, async () => { - httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse(getLoggingResponse(true)); + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ count: 5 }); - httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ - count: 5, + await act(async () => { + testBed = await setupOverviewPage(); }); + const { exists, component } = testBed; + + component.update(); + + expect(exists(`fixLogsStep-incomplete`)).toBe(true); + }); + + test(`It's incomplete when log collection is disabled `, async () => { + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ count: 0 }); + await act(async () => { testBed = await setupOverviewPage(); }); - const { exists, component } = testBed; + const { actions, exists, component } = testBed; component.update(); + expect(exists(`fixLogsStep-complete`)).toBe(true); + + httpRequestsMockHelpers.setUpdateDeprecationLoggingResponse(getLoggingResponse(false)); + + await actions.clickDeprecationToggle(); + expect(exists(`fixLogsStep-incomplete`)).toBe(true); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index c0977847d121c..2761ec20abdbf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -61,6 +61,15 @@ const FixLogsStep: FunctionComponent = ({ setIsComplete }) => { saveLogsCheckpoint(checkpoint); }, [checkpoint]); + useEffect(() => { + if (!state.isDeprecationLogIndexingEnabled) { + setIsComplete(false); + } + + // Depending upon setIsComplete would create an infinite loop. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [state.isDeprecationLogIndexingEnabled]); + return ( <> diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index 706732aa0027b..0a20df50cbf97 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -18,8 +18,6 @@ export { export { Storage } from '../../../../src/plugins/kibana_utils/public'; -export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; - export { DataPublicPluginStart } from '../../../../src/plugins/data/public'; export { APP_WRAPPER_CLASS } from '../../../../src/core/public'; From 521726d3d648a521d2a57d61e372f3ec68c4af36 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Fri, 10 Sep 2021 16:22:32 -0400 Subject: [PATCH 28/93] [Upgrade Assistant] Update copy to use "issues" instead of "warnings" (#111817) --- .../components/overview/fix_logs_step/fix_logs_step.tsx | 2 +- .../upgrade_assistant/public/application/lib/breadcrumbs.ts | 4 ++-- x-pack/plugins/upgrade_assistant/server/routes/status.test.ts | 2 +- x-pack/plugins/upgrade_assistant/server/routes/status.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index 2761ec20abdbf..e19f50d266885 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -23,7 +23,7 @@ const i18nTexts = { defaultMessage: 'Identify deprecated API use and update your applications', }), toggleTitle: i18n.translate('xpack.upgradeAssistant.overview.toggleTitle', { - defaultMessage: 'Log Elasticsearch deprecation warnings', + defaultMessage: 'Log Elasticsearch deprecation issues', }), analyzeTitle: i18n.translate('xpack.upgradeAssistant.overview.analyzeTitle', { defaultMessage: 'Analyze deprecation logs', diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts index 1beb759442f9f..3e30ffd06db15 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts @@ -16,12 +16,12 @@ const i18nTexts = { defaultMessage: 'Upgrade Assistant', }), esDeprecations: i18n.translate('xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel', { - defaultMessage: 'Elasticsearch deprecation warnings', + defaultMessage: 'Elasticsearch deprecation issues', }), kibanaDeprecations: i18n.translate( 'xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel', { - defaultMessage: 'Kibana deprecation warnings', + defaultMessage: 'Kibana deprecation issues', } ), }, diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts index 8c0398ce86afc..e442d3b4fd11c 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts @@ -77,7 +77,7 @@ describe('Status API', () => { expect(resp.payload).toEqual({ readyForUpgrade: false, details: - 'You have 1 Elasticsearch deprecation warnings and 1 Kibana deprecation warnings that must be resolved before upgrading.', + 'You have 1 Elasticsearch deprecation issue and 1 Kibana deprecation issue that must be resolved before upgrading.', }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.ts index 79c9baadcb852..aef97dcb7bd71 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.ts @@ -51,7 +51,7 @@ export function registerUpgradeStatusRoute({ router, lib: { handleEsError } }: R return i18n.translate('xpack.upgradeAssistant.status.deprecationsUnresolvedMessage', { defaultMessage: - 'You have {esTotalCriticalDeps} Elasticsearch deprecation warnings and {kibanaTotalCriticalDeps} Kibana deprecation warnings that must be resolved before upgrading.', + 'You have {esTotalCriticalDeps} Elasticsearch deprecation {esTotalCriticalDeps, plural, one {issue} other {issues}} and {kibanaTotalCriticalDeps} Kibana deprecation {kibanaTotalCriticalDeps, plural, one {issue} other {issues}} that must be resolved before upgrading.', values: { esTotalCriticalDeps, kibanaTotalCriticalDeps }, }); }; From 6734f0a58f18d571cb6d57b80f08251358108b0a Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 10 Sep 2021 14:49:23 -0700 Subject: [PATCH 29/93] Create common deprecation issues panel component in UA (#111231) * Refine success state behavior and add tests. * Refactor components into a components directory. * Refactor SCSS to colocate styles with their components. * Refactor tests to reduce boilerplate and clarify conditions under test. --- .../translations/translations/ja-JP.json | 7 - .../translations/translations/zh-CN.json | 6 - .../kibana_deprecations_service.mock.ts | 1 + .../elasticsearch_deprecation_issues.test.tsx | 186 +++++++++++++++ .../fix_issues_step/fix_issues_step.test.tsx | 222 ++---------------- .../kibana_deprecation_issues.test.tsx | 132 +++++++++++ ...{mocked_responses.ts => mock_es_issues.ts} | 20 +- .../fix_issues_step/_fix_issues_step.scss | 6 - .../components/_deprecation_issues_panel.scss | 24 ++ .../components/_es_stats_error.scss | 7 + .../components/deprecation_issues_panel.tsx | 135 +++++++++++ .../fix_issues_step/components/es_stats.tsx | 46 ++++ .../es_stats_error.tsx | 7 +- .../{kibana_stats => components}/index.ts | 1 + .../components/kibana_stats.tsx | 83 +++++++ .../components/no_deprecation_issues.tsx | 45 ++++ .../fix_issues_step/es_stats/es_stats.tsx | 118 ---------- .../fix_issues_step/es_stats/index.ts | 8 - .../fix_issues_step/fix_issues_step.tsx | 8 +- .../kibana_stats/kibana_stats.tsx | 155 ------------ .../fix_issues_step/no_deprecations/index.ts | 8 - .../no_deprecations/no_deprecations.tsx | 35 --- .../public/shared_imports.ts | 5 + 23 files changed, 706 insertions(+), 559 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/{mocked_responses.ts => mock_es_issues.ts} (66%) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_fix_issues_step.scss create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_deprecation_issues_panel.scss create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats.tsx rename x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/{es_stats => components}/es_stats_error.tsx (98%) rename x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/{kibana_stats => components}/index.ts (83%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_stats.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/no_deprecation_issues.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/index.ts delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/index.ts delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 676446aa94100..2ce59760e9705 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25220,17 +25220,10 @@ "xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.upgradeSnapshotErrorTitle": "スナップショットのアップグレードエラー", "xpack.upgradeAssistant.esDeprecations.pageDescription": "廃止予定のクラスターとインデックス設定をレビューします。アップグレード前に重要な問題を解決する必要があります。", "xpack.upgradeAssistant.esDeprecations.pageTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsTitle": "重大", - "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "ドキュメント", "xpack.upgradeAssistant.kibanaDeprecations.loadingText": "廃止予定を読み込んでいます...", "xpack.upgradeAssistant.kibanaDeprecations.pageTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel": "Kibanaには{criticalDeprecations}個の重大な廃止予定があります", - "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "重大", - "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "Kibana廃止予定の取得中にエラーが発生しました。", - "xpack.upgradeAssistant.kibanaDeprecationStats.statsTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecationStats.warningDeprecationsTitle": "警告", "xpack.upgradeAssistant.noDeprecationsPrompt.nextStepsDescription": "他のスタック廃止予定については、{overviewButton}を確認してください。", "xpack.upgradeAssistant.noDeprecationsPrompt.overviewLinkText": "概要ページ", "xpack.upgradeAssistant.overview.analyzeTitle": "廃止予定ログを分析", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 10d395800dda3..f8bcd021a7ad1 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25649,16 +25649,10 @@ "xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.upgradeSnapshotErrorTitle": "升级快照时出错", "xpack.upgradeAssistant.esDeprecations.pageDescription": "查看已弃用的群集和索引设置。在升级之前必须解决任何紧急问题。", "xpack.upgradeAssistant.esDeprecations.pageTitle": "Elasticsearch", - "xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsTitle": "紧急", - "xpack.upgradeAssistant.esDeprecationStats.statsTitle": "Elasticsearch", "xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel": "Kibana", "xpack.upgradeAssistant.kibanaDeprecations.docLinkText": "文档", "xpack.upgradeAssistant.kibanaDeprecations.loadingText": "正在加载弃用……", "xpack.upgradeAssistant.kibanaDeprecations.pageTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle": "紧急", - "xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage": "检索 Kibana 弃用时发生错误。", - "xpack.upgradeAssistant.kibanaDeprecationStats.statsTitle": "Kibana", - "xpack.upgradeAssistant.kibanaDeprecationStats.warningDeprecationsTitle": "警告", "xpack.upgradeAssistant.noDeprecationsPrompt.nextStepsDescription": "查看{overviewButton}以了解其他 Stack 弃用。", "xpack.upgradeAssistant.noDeprecationsPrompt.overviewLinkText": "“概览”页面", "xpack.upgradeAssistant.overview.analyzeTitle": "分析弃用日志", diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts index 761f950bd7daf..fb3c48785c5f0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import type { DeprecationsServiceStart, DomainDeprecationDetails } from 'kibana/public'; const kibanaDeprecations: DomainDeprecationDetails[] = [ diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx new file mode 100644 index 0000000000000..d3c92625c7a34 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx @@ -0,0 +1,186 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../../helpers'; +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; +import { + esCriticalAndWarningDeprecations, + esCriticalOnlyDeprecations, + esNoDeprecations, +} from './mock_es_issues'; + +describe('Overview - Fix deprecation issues step - Elasticsearch deprecations', () => { + let testBed: OverviewTestBed; + const { server, httpRequestsMockHelpers } = setupEnvironment(); + + afterAll(() => { + server.restore(); + }); + + describe('When load succeeds', () => { + const setup = async () => { + // Set up with no Kibana deprecations. + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService, response: [] }); + + testBed = await setupOverviewPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { component } = testBed; + component.update(); + }; + + describe('when there are critical and warning issues', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esCriticalAndWarningDeprecations); + await setup(); + }); + + test('renders counts for both', () => { + const { exists, find } = testBed; + expect(exists('esStatsPanel')).toBe(true); + expect(find('esStatsPanel.warningDeprecations').text()).toContain('1'); + expect(find('esStatsPanel.criticalDeprecations').text()).toContain('1'); + }); + + test('panel links to ES deprecations page', () => { + const { component, find } = testBed; + component.update(); + expect(find('esStatsPanel').find('a').props().href).toBe('/es_deprecations'); + }); + }); + + describe('when there are critical but no warning issues', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esCriticalOnlyDeprecations); + await setup(); + }); + + test('renders a count for critical issues and success state for warning issues', () => { + const { exists, find } = testBed; + expect(exists('esStatsPanel')).toBe(true); + expect(find('esStatsPanel.criticalDeprecations').text()).toContain('1'); + expect(exists('esStatsPanel.noWarningDeprecationIssues')).toBe(true); + }); + + test('panel links to ES deprecations page', () => { + const { component, find } = testBed; + component.update(); + expect(find('esStatsPanel').find('a').props().href).toBe('/es_deprecations'); + }); + }); + + describe('when there no critical or warning issues', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esNoDeprecations); + await setup(); + }); + + test('renders a count for critical issues and success state for warning issues', () => { + const { exists } = testBed; + expect(exists('esStatsPanel')).toBe(true); + expect(exists('esStatsPanel.noDeprecationIssues')).toBe(true); + }); + + test(`panel doesn't link to ES deprecations page`, () => { + const { component, find } = testBed; + component.update(); + expect(find('esStatsPanel').find('a').length).toBe(0); + }); + }); + }); + + describe(`When there's a load error`, () => { + test('handles network failure', async () => { + const error = { + statusCode: 500, + error: 'Internal server error', + message: 'Internal server error', + }; + + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { component, exists } = testBed; + component.update(); + expect(exists('esRequestErrorIconTip')).toBe(true); + }); + + test('handles unauthorized error', async () => { + const error = { + statusCode: 403, + error: 'Forbidden', + message: 'Forbidden', + }; + + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { component, exists } = testBed; + component.update(); + expect(exists('unauthorizedErrorIconTip')).toBe(true); + }); + + test('handles partially upgraded error', async () => { + const error = { + statusCode: 426, + error: 'Upgrade required', + message: 'There are some nodes running a different version of Elasticsearch', + attributes: { + allNodesUpgraded: false, + }, + }; + + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); + + await act(async () => { + testBed = await setupOverviewPage({ isReadOnlyMode: false }); + }); + + const { component, exists } = testBed; + component.update(); + expect(exists('partiallyUpgradedErrorIconTip')).toBe(true); + }); + + test('handles upgrade error', async () => { + const error = { + statusCode: 426, + error: 'Upgrade required', + message: 'There are some nodes running a different version of Elasticsearch', + attributes: { + allNodesUpgraded: true, + }, + }; + + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); + + await act(async () => { + testBed = await setupOverviewPage({ isReadOnlyMode: false }); + }); + + const { component, exists } = testBed; + component.update(); + expect(exists('upgradedErrorIconTip')).toBe(true); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx index 0b572ab41deaa..e9fa57b54ae0e 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx @@ -10,47 +10,23 @@ import { deprecationsServiceMock } from 'src/core/public/mocks'; import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../../helpers'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; -import { esDeprecations, esDeprecationsEmpty } from './mocked_responses'; +import { esCriticalAndWarningDeprecations, esNoDeprecations } from './mock_es_issues'; describe('Overview - Fix deprecation issues step', () => { let testBed: OverviewTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); - const { - mockedCriticalKibanaDeprecations, - mockedWarningKibanaDeprecations, - } = kibanaDeprecationsServiceHelpers.defaultMockedResponses; - - beforeEach(async () => { - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecations); - - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService }); - - testBed = await setupOverviewPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - const { component } = testBed; - component.update(); - }); afterAll(() => { server.restore(); }); - describe('Step status', () => { - test(`It's complete when there are no critical deprecations`, async () => { - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecationsEmpty); + describe('when there are critical issues in one panel', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esCriticalAndWarningDeprecations); await act(async () => { const deprecationService = deprecationsServiceMock.createStartContract(); - deprecationService.getAllDeprecations = jest.fn().mockRejectedValue([]); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService, response: [] }); testBed = await setupOverviewPage({ services: { @@ -61,153 +37,19 @@ describe('Overview - Fix deprecation issues step', () => { }); }); - const { exists, component } = testBed; - - component.update(); - - expect(exists(`fixIssuesStep-complete`)).toBe(true); + testBed.component.update(); }); - test(`It's incomplete when there are critical deprecations`, async () => { + test('renders step as incomplete', async () => { const { exists } = testBed; - expect(exists(`fixIssuesStep-incomplete`)).toBe(true); }); }); - describe('ES deprecations', () => { - test('Shows deprecation warning and critical counts', () => { - const { exists, find } = testBed; - - expect(exists('esStatsPanel')).toBe(true); - expect(find('esStatsPanel.warningDeprecations').text()).toContain('1'); - expect(find('esStatsPanel.criticalDeprecations').text()).toContain('1'); - }); - - test(`Hides deprecation counts if it doesn't have any`, async () => { - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecationsEmpty); + describe('when there are no critical issues for either panel', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esNoDeprecations); - await act(async () => { - testBed = await setupOverviewPage(); - }); - - const { exists } = testBed; - - expect(exists('noDeprecationsLabel')).toBe(true); - }); - - test('Stats panel contains link to ES deprecations page', () => { - const { component, exists, find } = testBed; - - component.update(); - - expect(exists('esStatsPanel')).toBe(true); - expect(find('esStatsPanel').find('a').props().href).toBe('/es_deprecations'); - }); - - describe('Renders errors', () => { - test('handles network failure', async () => { - const error = { - statusCode: 500, - error: 'Internal server error', - message: 'Internal server error', - }; - - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - - await act(async () => { - testBed = await setupOverviewPage(); - }); - - const { component, exists } = testBed; - - component.update(); - - expect(exists('esRequestErrorIconTip')).toBe(true); - }); - - test('handles unauthorized error', async () => { - const error = { - statusCode: 403, - error: 'Forbidden', - message: 'Forbidden', - }; - - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - - await act(async () => { - testBed = await setupOverviewPage(); - }); - - const { component, exists } = testBed; - - component.update(); - - expect(exists('unauthorizedErrorIconTip')).toBe(true); - }); - - test('handles partially upgraded error', async () => { - const error = { - statusCode: 426, - error: 'Upgrade required', - message: 'There are some nodes running a different version of Elasticsearch', - attributes: { - allNodesUpgraded: false, - }, - }; - - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - - await act(async () => { - testBed = await setupOverviewPage({ isReadOnlyMode: false }); - }); - - const { component, exists } = testBed; - - component.update(); - - expect(exists('partiallyUpgradedErrorIconTip')).toBe(true); - }); - - test('handles upgrade error', async () => { - const error = { - statusCode: 426, - error: 'Upgrade required', - message: 'There are some nodes running a different version of Elasticsearch', - attributes: { - allNodesUpgraded: true, - }, - }; - - httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - - await act(async () => { - testBed = await setupOverviewPage({ isReadOnlyMode: false }); - }); - - const { component, exists } = testBed; - - component.update(); - - expect(exists('upgradedErrorIconTip')).toBe(true); - }); - }); - }); - - describe('Kibana deprecations', () => { - test('Shows deprecation warning and critical counts', () => { - const { exists, find } = testBed; - - expect(exists('kibanaStatsPanel')).toBe(true); - expect(find('kibanaStatsPanel.warningDeprecations').text()).toContain( - mockedWarningKibanaDeprecations.length - ); - expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain( - mockedCriticalKibanaDeprecations.length - ); - }); - - test(`Hides deprecation count if it doesn't have any`, async () => { await act(async () => { const deprecationService = deprecationsServiceMock.createStartContract(); kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService, response: [] }); @@ -221,48 +63,12 @@ describe('Overview - Fix deprecation issues step', () => { }); }); - const { exists, component } = testBed; - - component.update(); - - expect(exists('noDeprecationsLabel')).toBe(true); - expect(exists('kibanaStatsPanel.warningDeprecations')).toBe(false); - expect(exists('kibanaStatsPanel.criticalDeprecations')).toBe(false); - }); - - test('Stats panel contains link to Kibana deprecations page', () => { - const { component, exists, find } = testBed; - - component.update(); - - expect(exists('kibanaStatsPanel')).toBe(true); - expect(find('kibanaStatsPanel').find('a').props().href).toBe('/kibana_deprecations'); + testBed.component.update(); }); - describe('Renders errors', () => { - test('Handles network failure', async () => { - await act(async () => { - const deprecationService = deprecationsServiceMock.createStartContract(); - kibanaDeprecationsServiceHelpers.setLoadDeprecations({ - deprecationService, - mockRequestErrorMessage: 'Internal Server Error', - }); - - testBed = await setupOverviewPage({ - services: { - core: { - deprecations: deprecationService, - }, - }, - }); - }); - - const { component, exists } = testBed; - - component.update(); - - expect(exists('kibanaRequestErrorIconTip')).toBe(true); - }); + test('renders step as complete', async () => { + const { exists } = testBed; + expect(exists(`fixIssuesStep-complete`)).toBe(true); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx new file mode 100644 index 0000000000000..4c54f5c6932c6 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx @@ -0,0 +1,132 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; +import type { DomainDeprecationDetails } from 'kibana/public'; + +import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../../helpers'; +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; +import { esNoDeprecations } from './mock_es_issues'; + +describe('Overview - Fix deprecation issues step - Kibana deprecations', () => { + let testBed: OverviewTestBed; + const { server, httpRequestsMockHelpers } = setupEnvironment(); + const { + mockedKibanaDeprecations, + mockedCriticalKibanaDeprecations, + } = kibanaDeprecationsServiceHelpers.defaultMockedResponses; + + afterAll(() => { + server.restore(); + }); + + describe('When load succeeds', () => { + const setup = async (response: DomainDeprecationDetails[]) => { + // Set up with no ES deprecations. + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esNoDeprecations); + + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService, response }); + + testBed = await setupOverviewPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { component } = testBed; + component.update(); + }; + + describe('when there are critical and warning issues', () => { + beforeEach(async () => { + await setup(mockedKibanaDeprecations); + }); + + test('renders counts for both', () => { + const { exists, find } = testBed; + + expect(exists('kibanaStatsPanel')).toBe(true); + expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain(1); + expect(find('kibanaStatsPanel.warningDeprecations').text()).toContain(1); + }); + + test('panel links to Kibana deprecations page', () => { + const { component, find } = testBed; + component.update(); + expect(find('kibanaStatsPanel').find('a').props().href).toBe('/kibana_deprecations'); + }); + }); + + describe('when there are critical but no warning issues', () => { + beforeEach(async () => { + await setup(mockedCriticalKibanaDeprecations); + }); + + test('renders a count for critical issues and success state for warning issues', () => { + const { exists, find } = testBed; + + expect(exists('kibanaStatsPanel')).toBe(true); + expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain(1); + expect(exists('kibanaStatsPanel.noWarningDeprecationIssues')).toBe(true); + }); + + test('panel links to Kibana deprecations page', () => { + const { component, find } = testBed; + component.update(); + expect(find('kibanaStatsPanel').find('a').props().href).toBe('/kibana_deprecations'); + }); + }); + + describe('when there no critical or warning issues', () => { + beforeEach(async () => { + await setup([]); + }); + + test('renders a success state for the panel', () => { + const { exists } = testBed; + expect(exists('kibanaStatsPanel')).toBe(true); + expect(exists('kibanaStatsPanel.noDeprecationIssues')).toBe(true); + }); + + test(`panel doesn't link to Kibana deprecations page`, () => { + const { component, find } = testBed; + component.update(); + expect(find('kibanaStatsPanel').find('a').length).toBe(0); + }); + }); + }); + + describe(`When there's a load error`, () => { + test('Handles network failure', async () => { + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + kibanaDeprecationsServiceHelpers.setLoadDeprecations({ + deprecationService, + mockRequestErrorMessage: 'Internal Server Error', + }); + + testBed = await setupOverviewPage({ + services: { + core: { + deprecations: deprecationService, + }, + }, + }); + }); + + const { component, exists } = testBed; + component.update(); + expect(exists('kibanaRequestErrorIconTip')).toBe(true); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts similarity index 66% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts index ece52b344cc22..e3fd9a2dad693 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mocked_responses.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts @@ -7,7 +7,7 @@ import { ESUpgradeStatus } from '../../../../common/types'; -export const esDeprecations: ESUpgradeStatus = { +export const esCriticalAndWarningDeprecations: ESUpgradeStatus = { totalCriticalDeprecations: 1, deprecations: [ { @@ -32,7 +32,23 @@ export const esDeprecations: ESUpgradeStatus = { ], }; -export const esDeprecationsEmpty: ESUpgradeStatus = { +export const esCriticalOnlyDeprecations: ESUpgradeStatus = { + totalCriticalDeprecations: 1, + deprecations: [ + { + isCritical: true, + type: 'cluster_settings', + resolveDuringUpgrade: false, + message: 'Index Lifecycle Management poll interval is set too low', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#ilm-poll-interval-limit', + details: + 'The Index Lifecycle Management poll interval setting [indices.lifecycle.poll_interval] is currently set to [500ms], but must be 1s or greater', + }, + ], +}; + +export const esNoDeprecations: ESUpgradeStatus = { totalCriticalDeprecations: 0, deprecations: [], }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_fix_issues_step.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_fix_issues_step.scss deleted file mode 100644 index b32f3eb9ddbdf..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/_fix_issues_step.scss +++ /dev/null @@ -1,6 +0,0 @@ -// Used by both es_stats and kibana_stats panel for having the EuiPopover Icon -// for errors shown next to the title without having to resort to wrapping everything -// with EuiFlexGroups. -.upgWarningIcon { - margin-left: $euiSizeS; -} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_deprecation_issues_panel.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_deprecation_issues_panel.scss new file mode 100644 index 0000000000000..37079275b1859 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_deprecation_issues_panel.scss @@ -0,0 +1,24 @@ +/** + * Push success state to the bottom + * of the card, so it aligns with , + * which is inside EuiStat. + */ +.upgDeprecationIssuesPanel .euiCard__content { + display: flex; + flex-direction: column; + justify-content: space-between; +} + +/** + * Ensure the stat is a consistent height, even when it contains + * , which is shorter than the + * standard number value. We also push it to the bottom of the its + * container, to base-align it with the number value. + */ +.upgDeprecationIssuesPanel__stat { + height: 60px; // Derived from font measurements, not sizing vars + justify-content: space-between; + flex-grow: 1; + flex-direction: column; + display: flex; +} \ No newline at end of file diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss new file mode 100644 index 0000000000000..92c92d96c31a2 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss @@ -0,0 +1,7 @@ +/* + * Used for having the EuiPopover Icon for errors shown next to the title without + * having to resort to wrapping everything with EuiFlexGroups. + */ +.upgWarningIcon { + margin-left: $euiSizeS; +} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx new file mode 100644 index 0000000000000..d5b94b89f5443 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx @@ -0,0 +1,135 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; +import { EuiCard, EuiStat, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { reactRouterNavigate } from '../../../../../shared_imports'; +import { getDeprecationsUpperLimit } from '../../../../lib/utils'; +import { NoDeprecationIssues } from './no_deprecation_issues'; + +import './_deprecation_issues_panel.scss'; + +const i18nTexts = { + warningDeprecationsTitle: i18n.translate( + 'xpack.upgradeAssistant.deprecationStats.warningDeprecationsTitle', + { + defaultMessage: 'Warning', + } + ), + criticalDeprecationsTitle: i18n.translate( + 'xpack.upgradeAssistant.deprecationStats.criticalDeprecationsTitle', + { + defaultMessage: 'Critical', + } + ), +}; + +interface Props { + 'data-test-subj': string; + deprecationSource: string; + linkUrl: string; + criticalDeprecationsCount: number; + warningDeprecationsCount: number; + isLoading: boolean; + errorMessage?: JSX.Element | null; + setIsFixed: (isFixed: boolean) => void; +} + +export const DeprecationIssuesPanel = (props: Props) => { + const { + deprecationSource, + linkUrl, + criticalDeprecationsCount, + warningDeprecationsCount, + isLoading, + errorMessage, + setIsFixed, + } = props; + const history = useHistory(); + + const hasError = !!errorMessage; + const hasCriticalIssues = criticalDeprecationsCount > 0; + const hasWarningIssues = warningDeprecationsCount > 0; + const hasNoIssues = !isLoading && !hasError && !hasWarningIssues && !hasCriticalIssues; + + useEffect(() => { + if (!isLoading && !errorMessage) { + setIsFixed(criticalDeprecationsCount === 0); + } + }, [setIsFixed, criticalDeprecationsCount, isLoading, errorMessage]); + + return ( + + {deprecationSource} + {hasError && errorMessage} + + } + {...(!hasNoIssues && reactRouterNavigate(history, linkUrl))} + > + + + {hasNoIssues ? ( + + ) : ( + + + + ) + } + titleElement="span" + description={i18nTexts.criticalDeprecationsTitle} + titleColor="danger" + isLoading={isLoading} + /> + + + + + ) + } + titleElement="span" + description={i18nTexts.warningDeprecationsTitle} + isLoading={isLoading} + /> + + + )} + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats.tsx new file mode 100644 index 0000000000000..89860d5b58be4 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; + +import { useAppContext } from '../../../../app_context'; +import { EsStatsErrors } from './es_stats_error'; +import { DeprecationIssuesPanel } from './deprecation_issues_panel'; + +interface Props { + setIsFixed: (isFixed: boolean) => void; +} + +export const ElasticsearchDeprecationStats: FunctionComponent = ({ setIsFixed }) => { + const { + services: { api }, + } = useAppContext(); + + const { data: esDeprecations, isLoading, error } = api.useLoadEsDeprecations(); + + const criticalDeprecationsCount = + esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical)?.length ?? 0; + + const warningDeprecationsCount = + esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical === false) + ?.length ?? 0; + + const errorMessage = error && ; + + return ( + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats_error.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats_error.tsx similarity index 98% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats_error.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats_error.tsx index c717a8a2e12e8..7246d73db038c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats_error.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats_error.tsx @@ -6,11 +6,13 @@ */ import React from 'react'; - import { EuiIconTip } from '@elastic/eui'; + import { ResponseError } from '../../../../lib/api'; import { getEsDeprecationError } from '../../../../lib/get_es_deprecation_error'; +import './_es_stats_error.scss'; + interface Props { error: ResponseError; } @@ -34,6 +36,7 @@ export const EsStatsErrors: React.FunctionComponent = ({ error }) => { /> ); break; + case 'partially_upgraded_error': iconContent = ( = ({ error }) => { /> ); break; + case 'upgraded_error': iconContent = ( = ({ error }) => { /> ); break; + case 'request_error': default: iconContent = ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/index.ts similarity index 83% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/index.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/index.ts index 185ec5f2540c4..fe3a0dd2ceaff 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/index.ts @@ -5,4 +5,5 @@ * 2.0. */ +export { ElasticsearchDeprecationStats } from './es_stats'; export { KibanaDeprecationStats } from './kibana_stats'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_stats.tsx new file mode 100644 index 0000000000000..891ccc01dcd40 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_stats.tsx @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useEffect, useState } from 'react'; +import { EuiIconTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import type { DomainDeprecationDetails } from 'kibana/public'; + +import { useAppContext } from '../../../../app_context'; +import { DeprecationIssuesPanel } from './deprecation_issues_panel'; + +interface Props { + setIsFixed: (isFixed: boolean) => void; +} + +export const KibanaDeprecationStats: FunctionComponent = ({ setIsFixed }) => { + const { + services: { + core: { deprecations }, + }, + } = useAppContext(); + + const [kibanaDeprecations, setKibanaDeprecations] = useState< + DomainDeprecationDetails[] | undefined + >(undefined); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(undefined); + + useEffect(() => { + async function getAllDeprecations() { + setIsLoading(true); + + try { + const response = await deprecations.getAllDeprecations(); + setKibanaDeprecations(response); + } catch (e) { + setError(e); + } + + setIsLoading(false); + } + + getAllDeprecations(); + }, [deprecations]); + + const criticalDeprecationsCount = + kibanaDeprecations?.filter((deprecation) => deprecation.level === 'critical')?.length ?? 0; + + const warningDeprecationsCount = + kibanaDeprecations?.filter((deprecation) => deprecation.level === 'warning')?.length ?? 0; + + const errorMessage = error && ( + + ); + + return ( + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/no_deprecation_issues.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/no_deprecation_issues.tsx new file mode 100644 index 0000000000000..168a682ab6d33 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/no_deprecation_issues.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +const i18nTexts = { + noPartialDeprecationIssuesText: i18n.translate( + 'xpack.upgradeAssistant.noPartialDeprecationsMessage', + { + defaultMessage: 'None', + } + ), + noDeprecationIssuesText: i18n.translate('xpack.upgradeAssistant.noDeprecationsMessage', { + defaultMessage: 'No issues', + }), +}; + +interface Props { + isPartial?: boolean; + 'data-test-subj'?: string; +} + +export const NoDeprecationIssues: FunctionComponent = (props) => { + const { isPartial = false } = props; + + return ( + + + + + + + + {isPartial ? i18nTexts.noPartialDeprecationIssuesText : i18nTexts.noDeprecationIssuesText} + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx deleted file mode 100644 index 7d0dcacfaa207..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/es_stats.tsx +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent, useEffect, useMemo } from 'react'; -import { useHistory } from 'react-router-dom'; - -import { EuiStat, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiCard } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; -import { getDeprecationsUpperLimit } from '../../../../lib/utils'; -import { useAppContext } from '../../../../app_context'; -import { EsStatsErrors } from './es_stats_error'; -import { NoDeprecations } from '../no_deprecations'; - -const i18nTexts = { - statsTitle: i18n.translate('xpack.upgradeAssistant.esDeprecationStats.statsTitle', { - defaultMessage: 'Elasticsearch', - }), - warningDeprecationsTitle: i18n.translate( - 'xpack.upgradeAssistant.esDeprecationStats.warningDeprecationsTitle', - { - defaultMessage: 'Warning', - } - ), - criticalDeprecationsTitle: i18n.translate( - 'xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsTitle', - { - defaultMessage: 'Critical', - } - ), -}; - -interface Props { - setIsFixed: (isFixed: boolean) => void; -} - -export const ESDeprecationStats: FunctionComponent = ({ setIsFixed }) => { - const history = useHistory(); - const { - services: { api }, - } = useAppContext(); - - const { data: esDeprecations, isLoading, error } = api.useLoadEsDeprecations(); - - const warningDeprecations = useMemo( - () => - esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical === false) || [], - [esDeprecations] - ); - const criticalDeprecations = useMemo( - () => esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical) || [], - [esDeprecations] - ); - - useEffect(() => { - if (!isLoading && !error) { - setIsFixed(criticalDeprecations.length === 0); - } - }, [setIsFixed, criticalDeprecations, isLoading, error]); - - const hasWarnings = warningDeprecations.length > 0; - const hasCritical = criticalDeprecations.length > 0; - const hasNoDeprecations = !isLoading && !error && !hasWarnings && !hasCritical; - const shouldRenderStat = (forSection: boolean) => error || isLoading || forSection; - - return ( - - {i18nTexts.statsTitle} - {error && } - - } - {...(!hasNoDeprecations && reactRouterNavigate(history, '/es_deprecations'))} - > - - - {hasNoDeprecations && ( - - - - )} - - {shouldRenderStat(hasCritical) && ( - - - - )} - - {shouldRenderStat(hasWarnings) && ( - - - - )} - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/index.ts deleted file mode 100644 index daf2644c2477b..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/es_stats/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export { ESDeprecationStats } from './es_stats'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx index df9bf58198d9d..d4ecccdd5dc15 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx @@ -11,11 +11,9 @@ import { EuiText, EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; -import { ESDeprecationStats } from './es_stats'; -import { KibanaDeprecationStats } from './kibana_stats'; -import type { OverviewStepProps } from '../../types'; -import './_fix_issues_step.scss'; +import type { OverviewStepProps } from '../../types'; +import { ElasticsearchDeprecationStats, KibanaDeprecationStats } from './components'; const i18nTexts = { reviewStepTitle: i18n.translate('xpack.upgradeAssistant.overview.fixIssuesStepTitle', { @@ -45,7 +43,7 @@ const FixIssuesStep: FunctionComponent = ({ setIsComplete }) => { return ( - + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx deleted file mode 100644 index 2cfc555116ba6..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/kibana_stats/kibana_stats.tsx +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent, useEffect, useState } from 'react'; -import { useHistory } from 'react-router-dom'; - -import { EuiCard, EuiStat, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import type { DomainDeprecationDetails } from 'kibana/public'; -import { reactRouterNavigate } from '../../../../../../../../../src/plugins/kibana_react/public'; -import { getDeprecationsUpperLimit } from '../../../../lib/utils'; -import { useAppContext } from '../../../../app_context'; -import { NoDeprecations } from '../no_deprecations'; - -const i18nTexts = { - statsTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.statsTitle', { - defaultMessage: 'Kibana', - }), - warningDeprecationsTitle: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationStats.warningDeprecationsTitle', - { - defaultMessage: 'Warning', - } - ), - criticalDeprecationsTitle: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle', - { - defaultMessage: 'Critical', - } - ), - loadingError: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage', - { - defaultMessage: 'An error occurred while retrieving Kibana deprecations.', - } - ), -}; - -interface Props { - setIsFixed: (isFixed: boolean) => void; -} - -export const KibanaDeprecationStats: FunctionComponent = ({ setIsFixed }) => { - const history = useHistory(); - const { - services: { - core: { deprecations }, - }, - } = useAppContext(); - - const [kibanaDeprecations, setKibanaDeprecations] = useState< - DomainDeprecationDetails[] | undefined - >(undefined); - const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(undefined); - - useEffect(() => { - async function getAllDeprecations() { - setIsLoading(true); - - try { - const response = await deprecations.getAllDeprecations(); - setKibanaDeprecations(response); - } catch (e) { - setError(e); - } - - setIsLoading(false); - } - - getAllDeprecations(); - }, [deprecations]); - - const warningDeprecationsCount = - kibanaDeprecations?.filter((deprecation) => deprecation.level === 'warning')?.length ?? 0; - const criticalDeprecationsCount = - kibanaDeprecations?.filter((deprecation) => deprecation.level === 'critical')?.length ?? 0; - - useEffect(() => { - if (!isLoading && !error) { - setIsFixed(criticalDeprecationsCount === 0); - } - }, [setIsFixed, criticalDeprecationsCount, isLoading, error]); - - const hasCritical = criticalDeprecationsCount > 0; - const hasWarnings = warningDeprecationsCount > 0; - const hasNoDeprecations = !isLoading && !error && !hasWarnings && !hasCritical; - const shouldRenderStat = (forSection: boolean) => error || isLoading || forSection; - - return ( - - {i18nTexts.statsTitle} - {error && ( - - )} - - } - {...(!hasNoDeprecations && reactRouterNavigate(history, '/kibana_deprecations'))} - > - - - {hasNoDeprecations && ( - - - - )} - - {shouldRenderStat(hasCritical) && ( - - - - )} - - {shouldRenderStat(hasWarnings) && ( - - - - )} - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/index.ts deleted file mode 100644 index a2684505eb9c6..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export { NoDeprecations } from './no_deprecations'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx deleted file mode 100644 index bed92d3b92ccf..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/no_deprecations/no_deprecations.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent } from 'react'; - -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiIcon, EuiSpacer } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -const i18nTexts = { - noDeprecationsText: i18n.translate('xpack.upgradeAssistant.noDeprecationsText', { - defaultMessage: 'No warnings. Good to go!', - }), -}; - -export const NoDeprecations: FunctionComponent = () => { - return ( - <> - - - - - - - - {i18nTexts.noDeprecationsText} - - - - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index 0a20df50cbf97..6fee29cf12938 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -18,6 +18,11 @@ export { export { Storage } from '../../../../src/plugins/kibana_utils/public'; +export { + KibanaContextProvider, + reactRouterNavigate, +} from '../../../../src/plugins/kibana_react/public'; + export { DataPublicPluginStart } from '../../../../src/plugins/data/public'; export { APP_WRAPPER_CLASS } from '../../../../src/core/public'; From be511530f0078e2f91b3de535b25e36a372a0a0c Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Mon, 13 Sep 2021 08:43:03 -0400 Subject: [PATCH 30/93] [Upgrade Assistant] Fix Kibana deprecations warning message --- .../error_handling.test.ts | 24 ++++++++++++++++--- .../kibana_deprecations.tsx | 9 +++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts index dbe49dfb714b9..83e0a884a3119 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts @@ -20,14 +20,32 @@ describe('Error handling', () => { server.restore(); }); - test('handles plugin error', async () => { + test('handles plugin errors', async () => { await act(async () => { kibanaDeprecationsServiceHelpers.setLoadDeprecations({ deprecationService, response: [ ...kibanaDeprecationsServiceHelpers.defaultMockedResponses.mockedKibanaDeprecations, { - domainId: 'failed_plugin_id', + domainId: 'failed_plugin_id_1', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: `Failed to get deprecations info for plugin "failed_plugin_id".`, + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + { + domainId: 'failed_plugin_id_1', + title: 'Failed to fetch deprecations for "failed_plugin_id"', + message: `Failed to get deprecations info for plugin "failed_plugin_id".`, + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + { + domainId: 'failed_plugin_id_2', title: 'Failed to fetch deprecations for "failed_plugin_id"', message: `Failed to get deprecations info for plugin "failed_plugin_id".`, level: 'fetch_error', @@ -53,7 +71,7 @@ describe('Error handling', () => { expect(exists('kibanaDeprecationErrors')).toBe(true); expect(find('kibanaDeprecationErrors').text()).toContain( - 'List of deprecation issues might be incomplete' + 'Failed to get deprecation issues for these plugins: failed_plugin_id_1, failed_plugin_id_2.' ); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index eec233b7fda6a..aac563aa8d0bb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -144,9 +144,14 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) const deprecationErrors: string[] = []; allDeprecations.forEach((deprecation) => { - // Keep track of any deprecations that failed to fetch to show warning in UI + // Keep track of any plugin deprecations that failed to fetch to show warning in UI if (deprecation.level === 'fetch_error') { - deprecationErrors.push(deprecation.domainId); + // It's possible that a plugin registered more than one deprecation that could fail + // We only want to keep track of the unique plugin failures + const pluginErrorExists = deprecationErrors.includes(deprecation.domainId); + if (pluginErrorExists === false) { + deprecationErrors.push(deprecation.domainId); + } return; } From d7312b834e601d618a68018994569d4b88037ca7 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 14 Sep 2021 13:27:42 -0400 Subject: [PATCH 31/93] [Upgrade Assistant] Add support for API keys when reindexing (#111451) --- x-pack/plugins/upgrade_assistant/kibana.json | 2 +- .../lib/reindexing/credential_store.test.ts | 180 ++++++++++++++++-- .../server/lib/reindexing/credential_store.ts | 140 +++++++++++++- .../server/lib/reindexing/worker.ts | 15 +- .../upgrade_assistant/server/plugin.ts | 14 +- .../routes/reindex_indices/reindex_handler.ts | 16 +- .../reindex_indices/reindex_indices.test.ts | 7 +- .../routes/reindex_indices/reindex_indices.ts | 13 +- .../plugins/upgrade_assistant/server/types.ts | 2 + 9 files changed, 342 insertions(+), 47 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/kibana.json b/x-pack/plugins/upgrade_assistant/kibana.json index 4573be8fdc041..c70d5e461d5bc 100644 --- a/x-pack/plugins/upgrade_assistant/kibana.json +++ b/x-pack/plugins/upgrade_assistant/kibana.json @@ -9,6 +9,6 @@ }, "configPath": ["xpack", "upgrade_assistant"], "requiredPlugins": ["management", "data", "licensing", "features", "infra", "share"], - "optionalPlugins": ["usageCollection", "cloud"], + "optionalPlugins": ["usageCollection", "cloud", "security"], "requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils"] } diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts index 8bf9143d93dbc..8532e2e4eece4 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts @@ -5,33 +5,171 @@ * 2.0. */ +import { KibanaRequest } from 'src/core/server'; +import { loggingSystemMock, httpServerMock } from 'src/core/server/mocks'; +import { securityMock } from '../../../../security/server/mocks'; import { ReindexSavedObject } from '../../../common/types'; -import { Credential, credentialStoreFactory } from './credential_store'; +import { credentialStoreFactory } from './credential_store'; + +const basicAuthHeader = 'Basic abc'; + +const logMock = loggingSystemMock.create().get(); +const requestMock = KibanaRequest.from( + httpServerMock.createRawRequest({ + headers: { + authorization: basicAuthHeader, + }, + }) +); +const securityStartMock = securityMock.createStart(); + +const reindexOpMock = { + id: 'asdf', + attributes: { indexName: 'test', lastCompletedStep: 1, locked: null }, +} as ReindexSavedObject; describe('credentialStore', () => { - it('retrieves the same credentials for the same state', () => { - const creds = { key: '1' } as Credential; - const reindexOp = { - id: 'asdf', - attributes: { indexName: 'test', lastCompletedStep: 1, locked: null }, - } as ReindexSavedObject; - - const credStore = credentialStoreFactory(); - credStore.set(reindexOp, creds); - expect(credStore.get(reindexOp)).toEqual(creds); + it('retrieves the same credentials for the same state', async () => { + const credStore = credentialStoreFactory(logMock); + + await credStore.set({ + request: requestMock, + reindexOp: reindexOpMock, + security: securityStartMock, + }); + + expect(credStore.get(reindexOpMock)).toEqual({ + authorization: basicAuthHeader, + }); + }); + + it('does not retrieve credentials if the state changed', async () => { + const credStore = credentialStoreFactory(logMock); + + await credStore.set({ + request: requestMock, + reindexOp: reindexOpMock, + security: securityStartMock, + }); + + reindexOpMock.attributes.lastCompletedStep = 0; + + expect(credStore.get(reindexOpMock)).toBeUndefined(); + }); + + it('retrieves credentials after update', async () => { + const credStore = credentialStoreFactory(logMock); + + await credStore.set({ + request: requestMock, + reindexOp: reindexOpMock, + security: securityStartMock, + }); + + const updatedReindexOp = { + ...reindexOpMock, + attributes: { + ...reindexOpMock.attributes, + status: 0, + }, + }; + + await credStore.update({ + credential: { + authorization: basicAuthHeader, + }, + reindexOp: updatedReindexOp, + security: securityStartMock, + }); + + expect(credStore.get(updatedReindexOp)).toEqual({ + authorization: basicAuthHeader, + }); }); - it('does retrieve credentials if the state is changed', () => { - const creds = { key: '1' } as Credential; - const reindexOp = { - id: 'asdf', - attributes: { indexName: 'test', lastCompletedStep: 1, locked: null }, - } as ReindexSavedObject; + describe('API keys enabled', () => { + const apiKeyResultMock = { + id: 'api_key_id', + name: 'api_key_name', + api_key: '123', + }; + + const invalidateApiKeyResultMock = { + invalidated_api_keys: [apiKeyResultMock.api_key], + previously_invalidated_api_keys: [], + error_count: 0, + }; + + const base64ApiKey = Buffer.from(`${apiKeyResultMock.id}:${apiKeyResultMock.api_key}`).toString( + 'base64' + ); + + beforeEach(() => { + securityStartMock.authc.apiKeys.areAPIKeysEnabled.mockReturnValue(Promise.resolve(true)); + securityStartMock.authc.apiKeys.grantAsInternalUser.mockReturnValue( + Promise.resolve(apiKeyResultMock) + ); + securityStartMock.authc.apiKeys.invalidateAsInternalUser.mockReturnValue( + Promise.resolve(invalidateApiKeyResultMock) + ); + }); + + it('sets API key in authorization header', async () => { + const credStore = credentialStoreFactory(logMock); + + await credStore.set({ + request: requestMock, + reindexOp: reindexOpMock, + security: securityStartMock, + }); + + expect(credStore.get(reindexOpMock)).toEqual({ + authorization: `ApiKey ${base64ApiKey}`, + }); + }); + + it('invalidates API keys when a reindex operation is complete', async () => { + const credStore = credentialStoreFactory(logMock); + + await credStore.set({ + request: requestMock, + reindexOp: reindexOpMock, + security: securityStartMock, + }); + + await credStore.update({ + credential: { + authorization: `ApiKey ${base64ApiKey}`, + }, + reindexOp: { + ...reindexOpMock, + attributes: { + ...reindexOpMock.attributes, + status: 1, + }, + }, + security: securityStartMock, + }); + + expect(securityStartMock.authc.apiKeys.invalidateAsInternalUser).toHaveBeenCalled(); + }); + + it('falls back to user credentials when error granting API key', async () => { + const credStore = credentialStoreFactory(logMock); + + securityStartMock.authc.apiKeys.grantAsInternalUser.mockRejectedValue( + new Error('Error granting API key') + ); - const credStore = credentialStoreFactory(); - credStore.set(reindexOp, creds); + await credStore.set({ + request: requestMock, + reindexOp: reindexOpMock, + security: securityStartMock, + }); - reindexOp.attributes.lastCompletedStep = 0; - expect(credStore.get(reindexOp)).not.toBeDefined(); + expect(credStore.get(reindexOpMock)).toEqual({ + authorization: basicAuthHeader, + }); + }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts index 2c4f86824518a..66885a23cf96b 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts @@ -8,10 +8,73 @@ import { createHash } from 'crypto'; import stringify from 'json-stable-stringify'; -import { ReindexSavedObject } from '../../../common/types'; +import { KibanaRequest, Logger } from 'src/core/server'; + +import { SecurityPluginStart } from '../../../../security/server'; +import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; export type Credential = Record; +// Generates a stable hash for the reindex operation's current state. +const getHash = (reindexOp: ReindexSavedObject) => + createHash('sha256') + .update(stringify({ id: reindexOp.id, ...reindexOp.attributes })) + .digest('base64'); + +// Returns a base64-encoded API key string or undefined +const getApiKey = async ({ + request, + security, + reindexOpId, + apiKeysMap, +}: { + request: KibanaRequest; + security: SecurityPluginStart; + reindexOpId: string; + apiKeysMap: Map; +}): Promise => { + try { + const apiKeyResult = await security.authc.apiKeys.grantAsInternalUser(request, { + name: `ua_reindex_${reindexOpId}`, + role_descriptors: {}, + metadata: { + description: + 'Created by the Upgrade Assistant for a reindex operation; this can be safely deleted after Kibana is upgraded.', + }, + }); + + if (apiKeyResult) { + const { api_key: apiKey, id } = apiKeyResult; + // Store each API key per reindex operation so that we can later invalidate it when the reindex operation is complete + apiKeysMap.set(reindexOpId, id); + // Returns the base64 encoding of `id:api_key` + // This can be used when sending a request with an "Authorization: ApiKey xxx" header + return Buffer.from(`${id}:${apiKey}`).toString('base64'); + } + } catch (error) { + // There are a few edge cases were granting an API key could fail, + // in which case we fall back to using the requestor's credentials in memory + return undefined; + } +}; + +const invalidateApiKey = async ({ + apiKeyId, + security, + log, +}: { + apiKeyId: string; + security?: SecurityPluginStart; + log: Logger; +}) => { + try { + await security?.authc.apiKeys.invalidateAsInternalUser({ ids: [apiKeyId] }); + } catch (error) { + // Swallow error if there's a problem invalidating API key + log.debug(`Error invalidating API key for id ${apiKeyId}: ${error.message}`); + } +}; + /** * An in-memory cache for user credentials to be used for reindexing operations. When looking up * credentials, the reindex operation must be in the same state it was in when the credentials @@ -20,25 +83,82 @@ export type Credential = Record; */ export interface CredentialStore { get(reindexOp: ReindexSavedObject): Credential | undefined; - set(reindexOp: ReindexSavedObject, credential: Credential): void; + set(params: { + reindexOp: ReindexSavedObject; + request: KibanaRequest; + security?: SecurityPluginStart; + }): Promise; + update(params: { + reindexOp: ReindexSavedObject; + security?: SecurityPluginStart; + credential: Credential; + }): Promise; clear(): void; } -export const credentialStoreFactory = (): CredentialStore => { +export const credentialStoreFactory = (logger: Logger): CredentialStore => { const credMap = new Map(); - - // Generates a stable hash for the reindex operation's current state. - const getHash = (reindexOp: ReindexSavedObject) => - createHash('sha256') - .update(stringify({ id: reindexOp.id, ...reindexOp.attributes })) - .digest('base64'); + const apiKeysMap = new Map(); + const log = logger.get('credential_store'); return { get(reindexOp: ReindexSavedObject) { return credMap.get(getHash(reindexOp)); }, - set(reindexOp: ReindexSavedObject, credential: Credential) { + async set({ + reindexOp, + request, + security, + }: { + reindexOp: ReindexSavedObject; + request: KibanaRequest; + security?: SecurityPluginStart; + }) { + const areApiKeysEnabled = (await security?.authc.apiKeys.areAPIKeysEnabled()) ?? false; + + if (areApiKeysEnabled) { + const apiKey = await getApiKey({ + request, + security: security!, + reindexOpId: reindexOp.id, + apiKeysMap, + }); + + if (apiKey) { + credMap.set(getHash(reindexOp), { + ...request.headers, + authorization: `ApiKey ${apiKey}`, + }); + return; + } + } + + // Set the requestor's credentials in memory if apiKeys are not enabled + credMap.set(getHash(reindexOp), request.headers); + }, + + async update({ + reindexOp, + security, + credential, + }: { + reindexOp: ReindexSavedObject; + security?: SecurityPluginStart; + credential: Credential; + }) { + // If the reindex operation is completed... + if (reindexOp.attributes.status === ReindexStatus.completed) { + // ...and an API key is being used, invalidate it + const apiKeyId = apiKeysMap.get(reindexOp.id); + if (apiKeyId) { + await invalidateApiKey({ apiKeyId, security, log }); + apiKeysMap.delete(reindexOp.id); + return; + } + } + + // Otherwise, re-associate the credentials credMap.set(getHash(reindexOp), credential); }, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts index c598da93388c3..3491c92ef5953 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts @@ -7,6 +7,7 @@ import { IClusterClient, Logger, SavedObjectsClientContract, FakeRequest } from 'src/core/server'; import moment from 'moment'; +import { SecurityPluginStart } from '../../../../security/server'; import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; import { Credential, CredentialStore } from './credential_store'; import { reindexActionsFactory } from './reindex_actions'; @@ -46,15 +47,19 @@ export class ReindexWorker { private inProgressOps: ReindexSavedObject[] = []; private readonly reindexService: ReindexService; private readonly log: Logger; + private readonly security: SecurityPluginStart; constructor( private client: SavedObjectsClientContract, private credentialStore: CredentialStore, private clusterClient: IClusterClient, log: Logger, - private licensing: LicensingPluginSetup + private licensing: LicensingPluginSetup, + security: SecurityPluginStart ) { this.log = log.get('reindex_worker'); + this.security = security; + if (ReindexWorker.workerSingleton) { throw new Error(`More than one ReindexWorker cannot be created.`); } @@ -171,7 +176,11 @@ export class ReindexWorker { firstOpInQueue.attributes.indexName ); // Re-associate the credentials - this.credentialStore.set(firstOpInQueue, credential); + this.credentialStore.update({ + reindexOp: firstOpInQueue, + security: this.security, + credential, + }); } } @@ -223,7 +232,7 @@ export class ReindexWorker { reindexOp = await swallowExceptions(service.processNextStep, this.log)(reindexOp); // Update credential store with most recent state. - this.credentialStore.set(reindexOp, credential); + this.credentialStore.update({ reindexOp, security: this.security, credential }); }; } diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index b47400c065bdd..4c46b923f0650 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -6,7 +6,6 @@ */ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; - import { Plugin, CoreSetup, @@ -16,6 +15,7 @@ import { SavedObjectsClient, SavedObjectsServiceStart, } from '../../../../src/core/server'; +import { SecurityPluginStart } from '../../security/server'; import { InfraPluginSetup } from '../../infra/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; @@ -44,6 +44,10 @@ interface PluginsSetup { infra: InfraPluginSetup; } +interface PluginsStart { + security: SecurityPluginStart; +} + export class UpgradeAssistantServerPlugin implements Plugin { private readonly logger: Logger; private readonly credentialStore: CredentialStore; @@ -54,11 +58,12 @@ export class UpgradeAssistantServerPlugin implements Plugin { // Properties set at start private savedObjectsServiceStart?: SavedObjectsServiceStart; + private securityPluginStart?: SecurityPluginStart; private worker?: ReindexWorker; constructor({ logger, env }: PluginInitializerContext) { this.logger = logger.get(); - this.credentialStore = credentialStoreFactory(); + this.credentialStore = credentialStoreFactory(this.logger); this.kibanaVersion = env.packageInfo.version; } @@ -120,6 +125,7 @@ export class UpgradeAssistantServerPlugin implements Plugin { } return this.savedObjectsServiceStart; }, + getSecurityPlugin: () => this.securityPluginStart, lib: { handleEsError, }, @@ -141,8 +147,9 @@ export class UpgradeAssistantServerPlugin implements Plugin { } } - start({ savedObjects, elasticsearch }: CoreStart) { + start({ savedObjects, elasticsearch }: CoreStart, { security }: PluginsStart) { this.savedObjectsServiceStart = savedObjects; + this.securityPluginStart = security; // The ReindexWorker uses a map of request headers that contain the authentication credentials // for a given reindex. We cannot currently store these in an the .kibana index b/c we do not @@ -159,6 +166,7 @@ export class UpgradeAssistantServerPlugin implements Plugin { savedObjects: new SavedObjectsClient( this.savedObjectsServiceStart.createInternalRepository() ), + security: this.securityPluginStart, }); this.worker.start(); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts index fe9b95787b7d1..d81dc8cec4c53 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts @@ -6,9 +6,15 @@ */ import { i18n } from '@kbn/i18n'; -import { IScopedClusterClient, Logger, SavedObjectsClientContract } from 'kibana/server'; +import { + IScopedClusterClient, + Logger, + SavedObjectsClientContract, + KibanaRequest, +} from 'kibana/server'; import { LicensingPluginSetup } from '../../../../licensing/server'; +import { SecurityPluginStart } from '../../../../security/server'; import { ReindexOperation, ReindexStatus } from '../../../common/types'; @@ -23,22 +29,24 @@ interface ReindexHandlerArgs { indexName: string; log: Logger; licensing: LicensingPluginSetup; - headers: Record; + request: KibanaRequest; credentialStore: CredentialStore; reindexOptions?: { enqueue?: boolean; }; + security?: SecurityPluginStart; } export const reindexHandler = async ({ credentialStore, dataClient, - headers, + request, indexName, licensing, log, savedObjects, reindexOptions, + security, }: ReindexHandlerArgs): Promise => { const callAsCurrentUser = dataClient.asCurrentUser; const reindexActions = reindexActionsFactory(savedObjects, callAsCurrentUser); @@ -62,7 +70,7 @@ export const reindexHandler = async ({ : await reindexService.createReindexOperation(indexName, reindexOptions); // Add users credentials for the worker to use - credentialStore.set(reindexOp, headers); + await credentialStore.set({ reindexOp, request, security }); return reindexOp.attributes; }; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts index 08d9995ee6219..44331799a160b 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts @@ -6,7 +6,9 @@ */ import { kibanaResponseFactory } from 'src/core/server'; +import { loggingSystemMock } from 'src/core/server/mocks'; import { licensingMock } from '../../../../licensing/server/mocks'; +import { securityMock } from '../../../../security/server/mocks'; import { createMockRouter, MockRouter, routeHandlerContextMock } from '../__mocks__/routes.mock'; import { createRequestMock } from '../__mocks__/request.mock'; @@ -35,6 +37,8 @@ import { IndexGroup, ReindexSavedObject, ReindexStatus } from '../../../common/t import { credentialStoreFactory } from '../../lib/reindexing/credential_store'; import { registerReindexIndicesRoutes } from './reindex_indices'; +const logMock = loggingSystemMock.create().get(); + /** * Since these route callbacks are so thin, these serve simply as integration tests * to ensure they're wired up to the lib functions correctly. Business logic is tested @@ -44,7 +48,7 @@ describe('reindex API', () => { let routeDependencies: any; let mockRouter: MockRouter; - const credentialStore = credentialStoreFactory(); + const credentialStore = credentialStoreFactory(logMock); const worker = { includes: jest.fn(), forceRefresh: jest.fn(), @@ -56,6 +60,7 @@ describe('reindex API', () => { credentialStore, router: mockRouter, licensing: licensingMock.createSetup(), + getSecurityPlugin: () => securityMock.createStart(), }; registerReindexIndicesRoutes(routeDependencies, () => worker); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts index 5528c0847822a..6edc03d86cb85 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts @@ -15,6 +15,7 @@ import { } from '../../../../../../src/core/server'; import { LicensingPluginSetup } from '../../../../licensing/server'; +import { SecurityPluginStart } from '../../../../security/server'; import { ReindexStatus } from '../../../common/types'; @@ -45,6 +46,7 @@ interface CreateReindexWorker { credentialStore: CredentialStore; savedObjects: SavedObjectsClient; licensing: LicensingPluginSetup; + security: SecurityPluginStart; } export function createReindexWorker({ @@ -53,9 +55,10 @@ export function createReindexWorker({ credentialStore, savedObjects, licensing, + security, }: CreateReindexWorker) { const esClient = elasticsearchService.client; - return new ReindexWorker(savedObjects, credentialStore, esClient, logger, licensing); + return new ReindexWorker(savedObjects, credentialStore, esClient, logger, licensing, security); } const mapAnyErrorToKibanaHttpResponse = (e: any) => { @@ -83,7 +86,7 @@ const mapAnyErrorToKibanaHttpResponse = (e: any) => { }; export function registerReindexIndicesRoutes( - { credentialStore, router, licensing, log }: RouteDependencies, + { credentialStore, router, licensing, log, getSecurityPlugin }: RouteDependencies, getWorker: () => ReindexWorker ) { const BASE_PATH = `${API_BASE_PATH}/reindex`; @@ -117,8 +120,9 @@ export function registerReindexIndicesRoutes( indexName, log, licensing, - headers: request.headers, + request, credentialStore, + security: getSecurityPlugin(), }); // Kick the worker on this node to immediately pickup the new reindex operation. @@ -202,11 +206,12 @@ export function registerReindexIndicesRoutes( indexName, log, licensing, - headers: request.headers, + request, credentialStore, reindexOptions: { enqueue: true, }, + security: getSecurityPlugin(), }); results.enqueued.push(result); } catch (e) { diff --git a/x-pack/plugins/upgrade_assistant/server/types.ts b/x-pack/plugins/upgrade_assistant/server/types.ts index 6c9ed3e517118..09272d270333e 100644 --- a/x-pack/plugins/upgrade_assistant/server/types.ts +++ b/x-pack/plugins/upgrade_assistant/server/types.ts @@ -7,6 +7,7 @@ import { IRouter, Logger, SavedObjectsServiceStart } from 'src/core/server'; import { LicensingPluginSetup } from '../../licensing/server'; +import { SecurityPluginStart } from '../../security/server'; import { CredentialStore } from './lib/reindexing/credential_store'; import { handleEsError } from './shared_imports'; @@ -15,6 +16,7 @@ export interface RouteDependencies { credentialStore: CredentialStore; log: Logger; getSavedObjectsService: () => SavedObjectsServiceStart; + getSecurityPlugin: () => SecurityPluginStart | undefined; licensing: LicensingPluginSetup; lib: { handleEsError: typeof handleEsError; From 4e28dbde01577277901aa8e36da605b942332f82 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 14 Sep 2021 19:36:56 -0400 Subject: [PATCH 32/93] [Upgrade Assistant] Update readme (#112154) --- x-pack/plugins/upgrade_assistant/README.md | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index 0c6c2a3f4c772..31b07d251145e 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -66,7 +66,28 @@ To test the Elasticsearch deprecations page ([#107053](https://github.com/elasti ``` yarn es snapshot -E path.data=./path_to_6.x_indices -``` + ``` + + **Token-based authentication** + + Reindexing should also work using token-based authentication (implemented via [#111451](https://github.com/elastic/kibana/pull/111451)). To simulate, set the following parameters when running ES from a snapshot: + + ``` + yarn es snapshot -E path.data=./path_to_6.x_indices -E xpack.security.authc.token.enabled=true -E xpack.security.authc.api_key.enabled=true + ``` + + Then, update your `kibana.dev.yml` file to include: + + ``` + xpack.security.authc.providers: + token: + token1: + order: 0 + showInSelector: true + enabled: true + ``` + + To verify it's working as expected, kick off a reindex task in UA. Then, navigate to **Security > API keys** and verify an API key was created. The name should be prefixed with `ua_reindex_`. Once the reindex task has completed successfully, the API key should be deleted. **2. Upgrading or deleting ML job model snapshots** From bbcd25d072ae7aee05eacf6e01cde972e68f3b0e Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 15 Sep 2021 10:56:58 +0200 Subject: [PATCH 33/93] [Upgrade Assistant] Make infra plugin optional (#111960) * Make infra plugin optional * Fix CR requests --- .../helpers/app_context.mock.ts | 1 + .../fix_logs_step/fix_logs_step.test.tsx | 11 +++++++ x-pack/plugins/upgrade_assistant/kibana.json | 4 +-- .../overview/fix_logs_step/external_links.tsx | 32 +++++++++++-------- .../upgrade_assistant/public/plugin.ts | 6 +++- .../plugins/upgrade_assistant/public/types.ts | 1 + .../upgrade_assistant/server/plugin.ts | 2 +- 7 files changed, 39 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index 42c05c2d80d37..46e3deda36fc9 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -74,6 +74,7 @@ export const getAppContextMock = () => ({ }, plugins: { share: shareMock, + infra: undefined, cloud: { ...cloudMock.createSetup(), isCloudEnabled: false, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index c81e0b2bd943e..96c0a874419a9 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -198,6 +198,9 @@ describe('Overview - Fix deprecation logs step', () => { prepend: (url: string) => url, }, }, + plugins: { + infra: {}, + }, }); }); @@ -211,6 +214,14 @@ describe('Overview - Fix deprecation logs step', () => { ); }); + test(`Doesn't show observability app link if infra app is not available`, async () => { + const { component, exists } = testBed; + + component.update(); + + expect(exists('viewObserveLogs')).toBe(false); + }); + test('Has a link to see logs in discover app', async () => { await act(async () => { testBed = await setupOverviewPage(); diff --git a/x-pack/plugins/upgrade_assistant/kibana.json b/x-pack/plugins/upgrade_assistant/kibana.json index c70d5e461d5bc..41789b393b68d 100644 --- a/x-pack/plugins/upgrade_assistant/kibana.json +++ b/x-pack/plugins/upgrade_assistant/kibana.json @@ -8,7 +8,7 @@ "githubTeam": "kibana-stack-management" }, "configPath": ["xpack", "upgrade_assistant"], - "requiredPlugins": ["management", "data", "licensing", "features", "infra", "share"], - "optionalPlugins": ["usageCollection", "cloud", "security"], + "requiredPlugins": ["management", "data", "licensing", "features", "share"], + "optionalPlugins": ["usageCollection", "cloud", "security", "infra"], "requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils"] } diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx index 7ced564fab204..d027b2f262e9e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx @@ -105,22 +105,26 @@ const ObservabilityAppLink: FunctionComponent = ({ checkpoint }) => { }; export const ExternalLinks: FunctionComponent = ({ checkpoint }) => { + const { infra: hasInfraPlugin } = useAppContext().plugins; + return ( - - - -

- -

-
- - -
-
+ {hasInfraPlugin && ( + + + +

+ +

+
+ + +
+
+ )} diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index 24a9d75a7508b..bafcae79acc13 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -43,7 +43,7 @@ export class UpgradeAssistantUIPlugin title: pluginName, order: 1, async mount(params) { - const [coreStart, { data }] = await coreSetup.getStartServices(); + const [coreStart, { data, ...plugins }] = await coreSetup.getStartServices(); const { chrome: { docTitle }, @@ -57,6 +57,10 @@ export class UpgradeAssistantUIPlugin plugins: { cloud, share, + // Infra plugin doesnt export anything as a public interface. So the only + // way we have at this stage for checking if the plugin is available or not + // is by checking if the startServices has the `infra` key. + infra: plugins.hasOwnProperty('infra') ? {} : undefined, }, services: { core: coreStart, diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index 55c43e452a864..4d47c10fdeec2 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -45,6 +45,7 @@ export interface AppDependencies { plugins: { cloud?: CloudSetup; share: SharePluginSetup; + infra: object | undefined; }; services: { core: CoreStart; diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index 4c46b923f0650..800aeecc57d55 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -99,7 +99,7 @@ export class UpgradeAssistantServerPlugin implements Plugin { // We need to initialize the deprecation logs plugin so that we can // navigate from this app to the observability app using a source_id. - infra.defineInternalSourceConfiguration(DEPRECATION_LOGS_SOURCE_ID, { + infra?.defineInternalSourceConfiguration(DEPRECATION_LOGS_SOURCE_ID, { name: 'deprecationLogs', description: 'deprecation logs', logIndices: { From cb16a6ea79ce32899c076e9a42acb16aca174337 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 15 Sep 2021 12:31:41 +0200 Subject: [PATCH 34/93] [Upgrade Assistant] Improve flyout information architecture (#111713) * Make sure longstrings inside flyout body are text-wrap * Show resolved badge for reindex flyout and row * Finish off rest of ES deprecation flyouts * Refactor deprecation badge into its own component * Add tests for kibana deprecations * Add tests for es deprecations * Also check that we have status=error before rendering error callout * Check for non-complete states instead of just error * Small refactor * Default deprecation is not resolvable * Add a bit more spacing between title and badge * Address CR changes * Use EuiSpacer instead of flexitems --- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../index_settings_deprecation_flyout.test.ts | 6 +- .../ml_snapshots_deprecation_flyout.test.ts | 24 ++--- .../deprecation_details_flyout.test.ts | 10 ++- .../deprecation_types/default/flyout.tsx | 8 +- .../deprecation_types/default/table_row.tsx | 3 +- .../index_settings/flyout.tsx | 6 ++ .../index_settings/table_row.tsx | 1 + .../deprecation_types/ml_snapshots/flyout.tsx | 89 ++++++++----------- .../ml_snapshots/table_row.tsx | 1 + .../reindex/flyout/checklist_step.tsx | 33 +++---- .../reindex/flyout/container.tsx | 6 ++ .../deprecation_types/reindex/table_row.tsx | 1 + .../es_deprecations_table_cells.tsx | 21 +---- .../deprecation_details_flyout.tsx | 18 ++-- .../kibana_deprecations_table.tsx | 33 +------ .../components/shared/deprecation_badge.tsx | 51 +++++++++++ .../application/components/shared/index.ts | 1 + 19 files changed, 171 insertions(+), 143 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_badge.tsx diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 2ce59760e9705..4f978b2207ba5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25173,7 +25173,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.backgroundResumeDetail": "再インデックスはバックグラウンドで継続しますが、Kibana がシャットダウンまたは再起動した場合、このページに戻り再インデックスを再開させる必要があります。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.calloutTitle": "インデックスは再インデックス中にドキュメントを投入、更新、または削除できません", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.cantStopDetail": "ドキュメントの更新を停止できない場合、または新しいクラスターに再インデックスする必要がある場合は、異なるアップグレード方法をお勧めします。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.doneLabel": "完了!", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.reindexingLabel": "再インデックス中…", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.resumeLabel": "再開", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.runReindexLabel": "再インデックスを実行", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f8bcd021a7ad1..15af05e9c5143 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25602,7 +25602,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.backgroundResumeDetail": "重新索引将在后台继续,但如果 Kibana 关闭或重新启动,您将需要返回此页,才能恢复重新索引。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.calloutTitle": "在重新索引时,索引无法采集、更新或删除文档", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.cantStopDetail": "如果您无法停止文档更新或需要重新索引到新的集群中,请考虑使用不同的升级策略。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.doneLabel": "已完成!", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.reindexingLabel": "正在重新索引……", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.resumeLabel": "恢复", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.runReindexLabel": "运行重新索引", diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts index e3cefe313063a..145cea24dde8b 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts @@ -47,12 +47,14 @@ describe('Index settings deprecation flyout', () => { }); it('removes deprecated index settings', async () => { - const { find, actions } = testBed; + const { find, actions, exists } = testBed; httpRequestsMockHelpers.setUpdateIndexSettingsResponse({ acknowledged: true, }); + expect(exists('indexSettingsDetails.warningDeprecationBadge')).toBe(true); + await actions.indexSettingsDeprecationFlyout.clickDeleteSettingsButton(); const request = server.requests[server.requests.length - 1]; @@ -75,6 +77,8 @@ describe('Index settings deprecation flyout', () => { expect(find('removeSettingsPrompt').length).toEqual(0); // Verify the action button no longer displays expect(find('indexSettingsDetails.deleteSettingsButton').length).toEqual(0); + // Verify the badge got marked as resolved + expect(exists('indexSettingsDetails.resolvedDeprecationBadge')).toBe(true); }); it('handles failure', async () => { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts index ff9dae03a2c57..bf20d52639699 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts @@ -48,7 +48,7 @@ describe('Machine learning deprecation flyout', () => { describe('upgrade snapshots', () => { it('successfully upgrades snapshots', async () => { - const { find, actions } = testBed; + const { find, actions, exists } = testBed; httpRequestsMockHelpers.setUpgradeMlSnapshotResponse({ nodeId: 'my_node', @@ -64,6 +64,7 @@ describe('Machine learning deprecation flyout', () => { status: 'complete', }); + expect(exists('mlSnapshotDetails.criticalDeprecationBadge')).toBe(true); expect(find('mlSnapshotDetails.upgradeSnapshotButton').text()).toEqual('Upgrade'); await actions.mlDeprecationFlyout.clickUpgradeSnapshot(); @@ -86,10 +87,11 @@ describe('Machine learning deprecation flyout', () => { // Reopen the flyout await actions.table.clickDeprecationRowAt('mlSnapshot', 0); - // Flyout actions should be disabled if deprecation was resolved - expect(find('mlSnapshotDetails.upgradeSnapshotButton').props().disabled).toBe(true); - expect(find('mlSnapshotDetails.upgradeSnapshotButton').text()).toContain('Upgrade complete'); - expect(find('mlSnapshotDetails.deleteSnapshotButton').props().disabled).toBe(true); + // Flyout actions should be hidden if deprecation was resolved + expect(exists('mlSnapshotDetails.upgradeSnapshotButton')).toBe(false); + expect(exists('mlSnapshotDetails.deleteSnapshotButton')).toBe(false); + // Badge should be updated in flyout title + expect(exists('mlSnapshotDetails.resolvedDeprecationBadge')).toBe(true); }); it('handles upgrade failure', async () => { @@ -133,12 +135,13 @@ describe('Machine learning deprecation flyout', () => { describe('delete snapshots', () => { it('successfully deletes snapshots', async () => { - const { find, actions } = testBed; + const { find, actions, exists } = testBed; httpRequestsMockHelpers.setDeleteMlSnapshotResponse({ acknowledged: true, }); + expect(exists('mlSnapshotDetails.criticalDeprecationBadge')).toBe(true); expect(find('mlSnapshotDetails.deleteSnapshotButton').text()).toEqual('Delete'); await actions.mlDeprecationFlyout.clickDeleteSnapshot(); @@ -158,10 +161,11 @@ describe('Machine learning deprecation flyout', () => { // Reopen the flyout await actions.table.clickDeprecationRowAt('mlSnapshot', 0); - // Flyout actions should be disabled if deprecation was resolved - expect(find('mlSnapshotDetails.deleteSnapshotButton').props().disabled).toBe(true); - expect(find('mlSnapshotDetails.deleteSnapshotButton').text()).toContain('Deletion complete'); - expect(find('mlSnapshotDetails.upgradeSnapshotButton').props().disabled).toBe(true); + // Flyout actions should be hidden if deprecation was resolved + expect(exists('mlSnapshotDetails.upgradeSnapshotButton')).toBe(false); + expect(exists('mlSnapshotDetails.deleteSnapshotButton')).toBe(false); + // Badge should be updated in flyout title + expect(exists('mlSnapshotDetails.resolvedDeprecationBadge')).toBe(true); }); it('handles delete failure', async () => { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts index f4f501221e595..11b7dc72ea5d2 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts @@ -47,6 +47,7 @@ describe('Kibana deprecation details flyout', () => { await actions.table.clickDeprecationAt(1); expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(exists('kibanaDeprecationDetails.warningDeprecationBadge')).toBe(true); expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe(manualDeprecation.title); expect(find('manualStepsList').find('li').length).toEqual( manualDeprecation.correctiveActions.manualSteps.length @@ -66,6 +67,7 @@ describe('Kibana deprecation details flyout', () => { await actions.table.clickDeprecationAt(0); expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(exists('kibanaDeprecationDetails.criticalDeprecationBadge')).toBe(true); expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe( quickResolveDeprecation.title ); @@ -87,8 +89,9 @@ describe('Kibana deprecation details flyout', () => { // Resolve information should not display and Quick resolve button should be disabled expect(exists('resolveSection')).toBe(false); - expect(find('resolveButton').props().disabled).toBe(true); - expect(find('resolveButton').text()).toContain('Resolved'); + expect(exists('resolveButton')).toBe(false); + // Badge should be updated in flyout title + expect(exists('kibanaDeprecationDetails.resolvedDeprecationBadge')).toBe(true); }); test('handles resolve failure', async () => { @@ -103,6 +106,7 @@ describe('Kibana deprecation details flyout', () => { await actions.table.clickDeprecationAt(0); expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(exists('kibanaDeprecationDetails.criticalDeprecationBadge')).toBe(true); expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe( quickResolveDeprecation.title ); @@ -123,6 +127,8 @@ describe('Kibana deprecation details flyout', () => { expect(exists('quickResolveError')).toBe(true); // Resolve information should display and Quick resolve button should be enabled expect(exists('resolveSection')).toBe(true); + // Badge should remain the same + expect(exists('kibanaDeprecationDetails.criticalDeprecationBadge')).toBe(true); expect(find('resolveButton').props().disabled).toBe(false); expect(find('resolveButton').text()).toContain('Try again'); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx index 9262ea9664033..c436d585db9ae 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx @@ -18,9 +18,11 @@ import { EuiText, EuiTextColor, EuiLink, + EuiSpacer, } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { DeprecationBadge } from '../../../shared'; export interface DefaultDeprecationFlyoutProps { deprecation: EnrichedDeprecationInfo; @@ -61,10 +63,10 @@ export const DefaultDeprecationFlyout = ({ return ( <> + + -

- {message} -

+

{message}

{index && ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/table_row.tsx index d4bacb21238cd..e7fc1bb7772d3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/table_row.tsx @@ -42,6 +42,7 @@ export const DefaultTableRow: React.FunctionComponent = ({ rowFieldNames, }, flyoutProps: { onClose: closeFlyout, + className: 'eui-textBreakWord', 'data-test-subj': 'defaultDeprecationDetails', 'aria-labelledby': 'defaultDeprecationDetailsFlyoutTitle', }, @@ -60,8 +61,8 @@ export const DefaultTableRow: React.FunctionComponent = ({ rowFieldNames, > setShowFlyout(true)} deprecation={deprecation} + openFlyout={() => setShowFlyout(true)} /> ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx index edb46ee0dc85b..24c1897fbdd02 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx @@ -26,6 +26,7 @@ import { import { EnrichedDeprecationInfo, IndexSettingAction } from '../../../../../../common/types'; import type { ResponseError } from '../../../../lib/api'; import type { Status } from '../../../types'; +import { DeprecationBadge } from '../../../shared'; export interface RemoveIndexSettingsFlyoutProps { deprecation: EnrichedDeprecationInfo; @@ -109,6 +110,11 @@ export const RemoveIndexSettingsFlyout = ({ return ( <> + +

{message}

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx index d7e940b96e605..997cf476c8378 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx @@ -73,6 +73,7 @@ export const IndexSettingsTableRow: React.FunctionComponent = ({ }, flyoutProps: { onClose: closeFlyout, + className: 'eui-textBreakWord', 'data-test-subj': 'indexSettingsDetails', 'aria-labelledby': 'indexSettingsDetailsFlyoutTitle', }, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index a972b7ec192d2..40921981dfa5e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -24,6 +24,7 @@ import { } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { DeprecationBadge } from '../../../shared'; import { MlSnapshotContext } from './context'; import { SnapshotState } from './use_snapshot_state'; @@ -51,12 +52,6 @@ const i18nTexts = { defaultMessage: 'Retry upgrade', } ), - upgradeResolvedButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.deleteResolvupgradeResolvedButtonLabeledButtonLabel', - { - defaultMessage: 'Upgrade complete', - } - ), closeButtonLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.closeButtonLabel', { @@ -75,12 +70,6 @@ const i18nTexts = { defaultMessage: 'Deleting…', } ), - deleteResolvedButtonLabel: i18n.translate( - 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.deleteResolvedButtonLabel', - { - defaultMessage: 'Deletion complete', - } - ), retryDeleteButtonLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.flyout.retryDeleteButtonLabel', { @@ -119,8 +108,6 @@ const getDeleteButtonLabel = (snapshotState: SnapshotState) => { switch (snapshotState.status) { case 'in_progress': return i18nTexts.deletingButtonLabel; - case 'complete': - return i18nTexts.deleteResolvedButtonLabel; case 'idle': default: return i18nTexts.deleteButtonLabel; @@ -138,8 +125,6 @@ const getUpgradeButtonLabel = (snapshotState: SnapshotState) => { switch (snapshotState.status) { case 'in_progress': return i18nTexts.upgradingButtonLabel; - case 'complete': - return i18nTexts.upgradeResolvedButtonLabel; case 'idle': default: return i18nTexts.upgradeButtonLabel; @@ -155,6 +140,8 @@ export const FixSnapshotsFlyout = ({ upgradeSnapshot, deleteSnapshot, }: FixSnapshotsFlyoutProps) => { + const isResolved = snapshotState.status === 'complete'; + const onUpgradeSnapshot = () => { upgradeSnapshot(); closeFlyout(); @@ -168,12 +155,14 @@ export const FixSnapshotsFlyout = ({ return ( <> + +

{i18nTexts.flyoutTitle}

- {snapshotState.error && ( + {snapshotState.error && !isResolved && ( <>
- - - - - {getDeleteButtonLabel(snapshotState)} - - - - - {getUpgradeButtonLabel(snapshotState)} - - - - + {!isResolved && ( + + + + + {getDeleteButtonLabel(snapshotState)} + + + + + {getUpgradeButtonLabel(snapshotState)} + + + + + )}
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx index e4221eb10a554..76d99373febb3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx @@ -50,6 +50,7 @@ export const MlSnapshotsTableRowCells: React.FunctionComponent = }, flyoutProps: { onClose: closeFlyout, + className: 'eui-textBreakWord', 'data-test-subj': 'mlSnapshotDetails', 'aria-labelledby': 'mlSnapshotDetailsFlyoutTitle', }, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx index 856e2a57649df..b0af397b16a30 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx @@ -41,13 +41,6 @@ const buttonLabel = (status?: ReindexStatus) => { defaultMessage="Reindexing…" /> ); - case ReindexStatus.completed: - return ( - - ); case ReindexStatus.paused: return (
- - - {buttonLabel(status)} - - + {status !== ReindexStatus.completed && ( + + + {buttonLabel(status)} + + + )}
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx index d2d07b47acd49..0a2e26b1ed886 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx @@ -21,6 +21,7 @@ import { useAppContext } from '../../../../../app_context'; import type { ReindexStateContext } from '../context'; import { ChecklistFlyoutStep } from './checklist_step'; import { WarningsFlyoutStep } from './warnings_step'; +import { DeprecationBadge } from '../../../../shared'; enum ReindexFlyoutStep { reindexWarnings, @@ -130,6 +131,11 @@ export const ReindexFlyout: React.FunctionComponent = ({ return ( <> + +

= ({ }, flyoutProps: { onClose: closeFlyout, + className: 'eui-textBreakWord', 'data-test-subj': 'reindexDetails', 'aria-labelledby': 'reindexDetailsFlyoutTitle', }, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx index 2e2299ec8b1e0..0a075e049495f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx @@ -7,10 +7,11 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiBadge, EuiLink, EuiText, EuiToolTip } from '@elastic/eui'; +import { EuiLink, EuiText, EuiToolTip } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../common/types'; import { DEPRECATION_TYPE_MAP } from '../constants'; import { DeprecationTableColumns } from '../types'; +import { DeprecationBadge } from '../shared'; interface Props { resolutionTableCell?: React.ReactNode; @@ -20,18 +21,6 @@ interface Props { } const i18nTexts = { - criticalBadgeLabel: i18n.translate( - 'xpack.upgradeAssistant.esDeprecations.defaultDeprecation.criticalBadgeLabel', - { - defaultMessage: 'Critical', - } - ), - warningBadgeLabel: i18n.translate( - 'xpack.upgradeAssistant.esDeprecations.defaultDeprecation.warningBadgeLabel', - { - defaultMessage: 'Warning', - } - ), manualCellLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.defaultDeprecation.manualCellLabel', { @@ -54,11 +43,7 @@ export const EsDeprecationsTableCells: React.FunctionComponent = ({ }) => { // "Status column" if (fieldName === 'isCritical') { - if (deprecation.isCritical === true) { - return {i18nTexts.criticalBadgeLabel}; - } - - return {i18nTexts.warningBadgeLabel}; + return ; } // "Issue" column diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index d9d7b50c87f0c..d41b0a95e7679 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -25,6 +25,7 @@ import { } from '@elastic/eui'; import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; +import { DeprecationBadge } from '../shared'; import './_deprecation_details_flyout.scss'; @@ -130,12 +131,18 @@ export const DeprecationDetailsFlyout = ({ deprecationResolutionState, }: DeprecationDetailsFlyoutProps) => { const { documentationUrl, message, correctiveActions, title } = deprecation; + const isCurrent = deprecationResolutionState?.id === deprecation.id; + const isResolved = isCurrent && deprecationResolutionState?.resolveDeprecationStatus === 'ok'; return ( <> + + -

{title}

+

+ {title} +

@@ -154,7 +161,7 @@ export const DeprecationDetailsFlyout = ({ )} -

{message}

+

{message}

{documentationUrl && (

@@ -168,7 +175,7 @@ export const DeprecationDetailsFlyout = ({ {/* Hide resolution steps if already resolved */} - {deprecationResolutionState?.resolveDeprecationStatus !== 'ok' && ( + {!isResolved && (

{correctiveActions.api && ( <> @@ -212,8 +219,8 @@ export const DeprecationDetailsFlyout = ({ - {/* Only show the "Quick resolve" button if deprecation supports it */} - {correctiveActions.api && ( + {/* Only show the "Quick resolve" button if deprecation supports it and deprecation is not yet resolved */} + {correctiveActions.api && !isResolved && ( {getQuickResolveButtonLabel(deprecationResolutionState)} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx index 1df9402c686aa..6a757d0cb2b0b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx @@ -6,18 +6,12 @@ */ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { - EuiInMemoryTable, - EuiBasicTableColumn, - EuiButton, - EuiLink, - EuiBadge, - Search, -} from '@elastic/eui'; +import { EuiInMemoryTable, EuiBasicTableColumn, EuiButton, EuiLink, Search } from '@elastic/eui'; import { PAGINATION_CONFIG } from '../constants'; import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; import { ResolutionTableCell } from './resolution_table_cell'; +import { DeprecationBadge } from '../shared'; const i18nTexts = { refreshButtonLabel: i18n.translate( @@ -80,18 +74,6 @@ const i18nTexts = { defaultMessage: 'Critical', } ), - criticalBadgeLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.table.criticalBadgeLabel', - { - defaultMessage: 'critical', - } - ), - warningBadgeLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.table.warningBadgeLabel', - { - defaultMessage: 'warning', - } - ), searchPlaceholderLabel: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecations.table.searchPlaceholderLabel', { @@ -121,16 +103,7 @@ export const KibanaDeprecationsTable: React.FunctionComponent = ({ truncateText: true, sortable: true, render: (level: KibanaDeprecationDetails['level']) => { - switch (level) { - case 'critical': - return {i18nTexts.criticalBadgeLabel}; - - case 'warning': - return {i18nTexts.warningBadgeLabel}; - - default: - return <>{''}; - } + return ; }, }, { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_badge.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_badge.tsx new file mode 100644 index 0000000000000..c0b8f0eb24304 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_badge.tsx @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiBadge } from '@elastic/eui'; + +const i18nTexts = { + criticalBadgeLabel: i18n.translate('xpack.upgradeAssistant.deprecationBadge.criticalBadgeLabel', { + defaultMessage: 'Critical', + }), + resolvedBadgeLabel: i18n.translate('xpack.upgradeAssistant.deprecationBadge.resolvedBadgeLabel', { + defaultMessage: 'Resolved', + }), + warningBadgeLabel: i18n.translate('xpack.upgradeAssistant.deprecationBadge.warningBadgeLabel', { + defaultMessage: 'Warning', + }), +}; + +interface Props { + isCritical: boolean; + isResolved?: boolean; +} + +export const DeprecationBadge: FunctionComponent = ({ isCritical, isResolved }) => { + if (isResolved) { + return ( + + {i18nTexts.resolvedBadgeLabel} + + ); + } + + if (isCritical) { + return ( + + {i18nTexts.criticalBadgeLabel} + + ); + } + + return ( + + {i18nTexts.warningBadgeLabel} + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts index 89bce0813b92f..9464b5ecb98ca 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts @@ -7,3 +7,4 @@ export { NoDeprecationsPrompt } from './no_deprecations'; export { DeprecationCount } from './deprecation_count'; +export { DeprecationBadge } from './deprecation_badge'; From 0f4bb6801fe3506e456e8a22165c32422746226e Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 15 Sep 2021 09:04:59 -0400 Subject: [PATCH 35/93] [Upgrade Assistant] Update readme (#112195) --- x-pack/plugins/upgrade_assistant/README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index 31b07d251145e..255eb94a0318c 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -199,7 +199,24 @@ To test the Elasticsearch deprecations page ([#107053](https://github.com/elasti ``` #### Kibana deprecations -To test the Kibana deprecations page, you will first need to create a set of deprecations that will be returned from the Kibana deprecations API. Refer to the [8.0 Kibana deprecations meta issue](https://github.com/elastic/kibana/issues/109166) for example deprecations and steps to reproduce. +To test the Kibana deprecations page, you will first need to create a set of deprecations that will be returned from the Kibana deprecations API. + +`reporting` is currently one of the only plugins that is registering a deprecation with an automated resolution (implemented via [#104303](https://github.com/elastic/kibana/pull/104303)). To trigger this deprecation: + +1. Add Kibana sample data. +2. Create a PDF report from the Dashboard (**Dashboard > Share > PDF reports > Generate PDFs**). This requires a trial license. +3. Issue the following request in Console: + +``` +PUT .reporting-*/_settings +{ + "settings": { + "index.lifecycle.name": null + } +} +``` + +For a complete list of Kibana deprecations, refer to the [8.0 Kibana deprecations meta issue](https://github.com/elastic/kibana/issues/109166). ### Errors From 3ed09c6c80d61fb975536ac57f4f2dea0f90c24d Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 16 Sep 2021 13:04:33 +0200 Subject: [PATCH 36/93] [Upgrade Assistant] Add integration tests for Overview page (#111370) * Add a11y tests for when overview page has toggle enabled * Add functional and accessibility tests for overview page * Load test files * Fix linter error * Navigate before asserting * Steps have now completion state * Remove duped word * Run setup only once, not per test * Address CR changes * No need to renavigate to the page Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../overview/upgrade_step/upgrade_step.tsx | 1 + .../accessibility/apps/upgrade_assistant.ts | 24 +++++-- ...rade_assistant.ts => deprecation_pages.ts} | 10 +-- .../apps/upgrade_assistant/index.ts | 3 +- .../apps/upgrade_assistant/overview_page.ts | 68 +++++++++++++++++++ .../page_objects/upgrade_assistant_page.ts | 12 ++++ 6 files changed, 104 insertions(+), 14 deletions(-) rename x-pack/test/functional/apps/upgrade_assistant/{upgrade_assistant.ts => deprecation_pages.ts} (89%) create mode 100644 x-pack/test/functional/apps/upgrade_assistant/overview_page.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx index cb8c88b9d2af2..dffdf39e5dd59 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx @@ -123,6 +123,7 @@ export const getUpgradeStep = ({ docLinks, nextMajor }: Props): EuiStepProps => return { title: i18nTexts.upgradeStepTitle(nextMajor), status: 'incomplete', + 'data-test-subj': 'upgradeStep', children: , }; }; diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 55873d98b4df9..38ade6e908859 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -76,11 +76,27 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } }); - it('Overview page', async () => { - await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { - return testSubjects.exists('overview'); + describe('Overview page', () => { + beforeEach(async () => { + await PageObjects.upgradeAssistant.navigateToPage(); + await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { + return testSubjects.exists('overview'); + }); + }); + + it('with logs collection disabled', async () => { + await a11y.testAppSnapshot(); + }); + + it('with logs collection enabled', async () => { + await PageObjects.upgradeAssistant.clickDeprecationLoggingToggle(); + + await retry.waitFor('UA external links title to be present', async () => { + return testSubjects.isDisplayed('externalLinksTitle'); + }); + + await a11y.testAppSnapshot(); }); - await a11y.testAppSnapshot(); }); describe('Elasticsearch deprecations page', () => { diff --git a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts similarity index 89% rename from x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts rename to x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts index 99d77a2423f47..ab989b0dabb83 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts @@ -55,8 +55,7 @@ export default function upgradeAssistantFunctionalTests({ const security = getService('security'); const log = getService('log'); - // Updated for the hiding of the UA UI. - describe.skip('Upgrade Checkup', function () { + describe.skip('Deprecation pages', function () { this.tags('skipFirefox'); before(async () => { @@ -85,13 +84,6 @@ export default function upgradeAssistantFunctionalTests({ await security.testUser.restoreDefaults(); }); - it('renders the Overview page', async () => { - await PageObjects.upgradeAssistant.navigateToPage(); - await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { - return testSubjects.exists('overview'); - }); - }); - it('renders the Elasticsearch deprecations page', async () => { await PageObjects.upgradeAssistant.navigateToPage(); await PageObjects.upgradeAssistant.clickEsDeprecationsPanel(); diff --git a/x-pack/test/functional/apps/upgrade_assistant/index.ts b/x-pack/test/functional/apps/upgrade_assistant/index.ts index cacf55c58dce2..d99d1cd033327 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/index.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/index.ts @@ -12,6 +12,7 @@ export default function upgradeCheckup({ loadTestFile }: FtrProviderContext) { this.tags('ciGroup4'); loadTestFile(require.resolve('./feature_controls')); - loadTestFile(require.resolve('./upgrade_assistant')); + loadTestFile(require.resolve('./deprecation_pages')); + loadTestFile(require.resolve('./overview_page')); }); } diff --git a/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts new file mode 100644 index 0000000000000..76663a9f57c89 --- /dev/null +++ b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 upgradeAssistantOverviewPageFunctionalTests({ + getService, + getPageObjects, +}: FtrProviderContext) { + const PageObjects = getPageObjects(['upgradeAssistant', 'common']); + const retry = getService('retry'); + const security = getService('security'); + const testSubjects = getService('testSubjects'); + const es = getService('es'); + + describe('Overview Page', function () { + this.tags('skipFirefox'); + + before(async () => { + await security.testUser.setRoles(['superuser']); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + }); + + beforeEach(async () => { + await PageObjects.upgradeAssistant.navigateToPage(); + + await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { + return testSubjects.exists('overview'); + }); + }); + + it('Should render all steps', async () => { + testSubjects.exists('backupStep-incomplete'); + testSubjects.exists('fixIssuesStep-incomplete'); + testSubjects.exists('fixLogsStep-incomplete'); + testSubjects.exists('upgradeStep'); + }); + + describe('fixLogsStep', () => { + before(async () => { + // Access to system indices will be deprecated and should generate a deprecation log + await es.indices.get({ index: '.kibana' }); + + await PageObjects.upgradeAssistant.clickDeprecationLoggingToggle(); + + await retry.waitFor('UA external links title to be present', async () => { + return testSubjects.isDisplayed('externalLinksTitle'); + }); + }); + + it('Shows warnings callout if there are deprecations', async () => { + testSubjects.exists('hasWarningsCallout'); + }); + + it('Shows no warnings callout if there are no deprecations', async () => { + await PageObjects.upgradeAssistant.clickResetLastCheckpointButton(); + testSubjects.exists('noWarningsCallout'); + }); + }); + }); +} diff --git a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts index e763145a715ff..54d7f3d452123 100644 --- a/x-pack/test/functional/page_objects/upgrade_assistant_page.ts +++ b/x-pack/test/functional/page_objects/upgrade_assistant_page.ts @@ -35,6 +35,18 @@ export class UpgradeAssistantPageObject extends FtrService { }); } + async clickDeprecationLoggingToggle() { + return await this.retry.try(async () => { + await this.testSubjects.click('deprecationLoggingToggle'); + }); + } + + async clickResetLastCheckpointButton() { + return await this.retry.try(async () => { + await this.testSubjects.click('resetLastStoredDate'); + }); + } + async clickKibanaDeprecationsPanel() { return await this.retry.try(async () => { await this.testSubjects.click('kibanaStatsPanel'); From d3f45e62aa09830d84d00534199e7f0fac40796c Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 20 Sep 2021 20:37:43 +0200 Subject: [PATCH 37/93] [Upgrade Assistant] Add note about compatibility headers (#110469) --- .../public/doc_links/doc_links_service.ts | 4 ++ .../fix_logs_step/fix_logs_step.test.tsx | 19 ++++++++ .../overview/fix_logs_step/fix_logs_step.tsx | 44 ++++++++++++++++++- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 2bbb4703ecd19..6e8e620049a56 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -224,6 +224,10 @@ export class DocLinksService { shardAllocationSettings: `${ELASTICSEARCH_DOCS}modules-cluster.html#cluster-shard-allocation-settings`, transportSettings: `${ELASTICSEARCH_DOCS}modules-network.html#common-network-settings`, typesRemoval: `${ELASTICSEARCH_DOCS}removal-of-types.html`, + deprecationLogging: `${ELASTICSEARCH_DOCS}logging.html#deprecation-logging`, + setupUpgrade: `${ELASTICSEARCH_DOCS}setup-upgrade.html`, + releaseHighlights: `${ELASTICSEARCH_DOCS}release-highlights.html`, + apiCompatibilityHeader: `${ELASTICSEARCH_DOCS}api-conventions.html#api-compatibility`, }, siem: { guide: `${SECURITY_SOLUTION_DOCS}index.html`, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index 96c0a874419a9..6da9612272992 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -182,6 +182,7 @@ describe('Overview - Fix deprecation logs step', () => { expect(exists('externalLinksTitle')).toBe(false); expect(exists('deprecationsCountTitle')).toBe(false); + expect(exists('apiCompatibilityNoteTitle')).toBe(false); }); }); @@ -370,4 +371,22 @@ describe('Overview - Fix deprecation logs step', () => { }); }); }); + + describe('Step 4 - API compatibility header', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadDeprecationLoggingResponse(getLoggingResponse(true)); + }); + + test('It shows copy with compatibility api header advice', async () => { + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, component } = testBed; + + component.update(); + + expect(exists('apiCompatibilityNoteTitle')).toBe(true); + }); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index e19f50d266885..d110661ad7b89 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -8,9 +8,11 @@ import React, { FunctionComponent, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiText, EuiSpacer, EuiPanel, EuiCallOut } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiText, EuiSpacer, EuiPanel, EuiLink, EuiCallOut } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; +import { useAppContext } from '../../../app_context'; import { ExternalLinks } from './external_links'; import { DeprecationsCountCheckpoint } from './deprecations_count_checkpoint'; import { useDeprecationLogging } from './use_deprecation_logging'; @@ -34,6 +36,28 @@ const i18nTexts = { defaultMessage: 'Resolve deprecation issues and verify your changes', } ), + apiCompatibilityNoteTitle: i18n.translate( + 'xpack.upgradeAssistant.overview.apiCompatibilityNoteTitle', + { + defaultMessage: 'Apply API compatibility headers (optional)', + } + ), + apiCompatibilityNoteBody: (docLink: string) => ( + + + + ), + }} + /> + ), onlyLogWritingEnabledTitle: i18n.translate( 'xpack.upgradeAssistant.overview.deprecationLogs.deprecationWarningTitle', { @@ -55,6 +79,11 @@ interface Props { const FixLogsStep: FunctionComponent = ({ setIsComplete }) => { const state = useDeprecationLogging(); + const { + services: { + core: { docLinks }, + }, + } = useAppContext(); const [checkpoint, setCheckpoint] = useState(loadLogsCheckpoint()); useEffect(() => { @@ -113,6 +142,19 @@ const FixLogsStep: FunctionComponent = ({ setIsComplete }) => { setCheckpoint={setCheckpoint} setHasNoDeprecationLogs={setIsComplete} /> + + + +

{i18nTexts.apiCompatibilityNoteTitle}

+
+ + +

+ {i18nTexts.apiCompatibilityNoteBody( + docLinks.links.elasticsearch.apiCompatibilityHeader + )} +

+
)} From b60be2ff2e6b3a1e27106402971233f55827ebd7 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 21 Sep 2021 14:49:32 -0700 Subject: [PATCH 38/93] Improve error states for Upgrade Assistant deprecation issues (#112457) * Simplify error state for deprecation issues panels. Remove . * Rename components from stats -> panel. * Create common error-reporting component for use in both Kibana and ES deprecations pages. * Align order of loading, error, and success states between these pages. * Change references to 'deprecations' -> 'deprecation issues'. * Fix tests for panels. * Add API integration test for handling auth error. * Fix TS errors. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../es_deprecations/error_handling.test.ts | 34 ++--- .../error_handling.test.ts | 7 +- .../elasticsearch_deprecation_issues.test.tsx | 22 ++-- .../kibana_deprecation_issues.test.tsx | 6 +- .../plugins/upgrade_assistant/common/types.ts | 2 + .../es_deprecations/es_deprecation_errors.tsx | 50 -------- .../es_deprecations/es_deprecations.tsx | 11 +- .../kibana_deprecations.tsx | 118 +++++++----------- .../components/_es_stats_error.scss | 7 -- .../components/deprecation_issues_panel.tsx | 17 ++- ...ts.tsx => es_deprecation_issues_panel.tsx} | 6 +- .../components/es_stats_error.tsx | 84 ------------- .../fix_issues_step/components/index.ts | 4 +- ...sx => kibana_deprecation_issues_panel.tsx} | 22 +--- .../components/loading_issues_error.tsx | 21 ++++ .../fix_issues_step/fix_issues_step.tsx | 6 +- .../deprecations_page_loading_error.tsx | 42 +++++++ .../application/components/shared/index.ts | 1 + .../lib/get_es_deprecation_error.ts | 4 +- .../apis/upgrade_assistant/es_deprecations.ts | 41 ++++++ .../apis/upgrade_assistant/index.ts | 1 + 21 files changed, 219 insertions(+), 287 deletions(-) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecation_errors.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss rename x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/{es_stats.tsx => es_deprecation_issues_panel.tsx} (84%) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats_error.tsx rename x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/{kibana_stats.tsx => kibana_deprecation_issues_panel.tsx} (77%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/loading_issues_error.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecations_page_loading_error.tsx create mode 100644 x-pack/test/api_integration/apis/upgrade_assistant/es_deprecations.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts index 6314b4630f850..2f0c8f0597ec3 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/error_handling.test.ts @@ -31,13 +31,10 @@ describe('Error handling', () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); }); - const { component, exists, find } = testBed; - + const { component, find } = testBed; component.update(); - - expect(exists('permissionsError')).toBe(true); - expect(find('permissionsError').text()).toContain( - 'You are not authorized to view Elasticsearch deprecations.' + expect(find('deprecationsPageLoadingError').text()).toContain( + 'You are not authorized to view Elasticsearch deprecation issues.' ); }); @@ -59,12 +56,11 @@ describe('Error handling', () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); }); - const { component, exists, find } = testBed; - + const { component, find } = testBed; component.update(); - - expect(exists('upgradedCallout')).toBe(true); - expect(find('upgradedCallout').text()).toContain('All Elasticsearch nodes have been upgraded.'); + expect(find('deprecationsPageLoadingError').text()).toContain( + 'All Elasticsearch nodes have been upgraded.' + ); }); it('shows partially upgrade error when nodes are running different versions', async () => { @@ -83,12 +79,9 @@ describe('Error handling', () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); }); - const { component, exists, find } = testBed; - + const { component, find } = testBed; component.update(); - - expect(exists('partiallyUpgradedWarning')).toBe(true); - expect(find('partiallyUpgradedWarning').text()).toContain( + expect(find('deprecationsPageLoadingError').text()).toContain( 'Upgrade Kibana to the same version as your Elasticsearch cluster. One or more nodes in the cluster is running a different version than Kibana.' ); }); @@ -106,11 +99,10 @@ describe('Error handling', () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); }); - const { component, exists, find } = testBed; - + const { component, find } = testBed; component.update(); - - expect(exists('requestError')).toBe(true); - expect(find('requestError').text()).toContain('Could not retrieve Elasticsearch deprecations.'); + expect(find('deprecationsPageLoadingError').text()).toContain( + 'Could not retrieve Elasticsearch deprecation issues.' + ); }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts index 83e0a884a3119..650af2025ee2b 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts @@ -91,12 +91,9 @@ describe('Error handling', () => { }); }); - const { component, exists, find } = testBed; - + const { component, find } = testBed; component.update(); - - expect(exists('kibanaRequestError')).toBe(true); - expect(find('kibanaRequestError').text()).toContain( + expect(find('deprecationsPageLoadingError').text()).toContain( 'Could not retrieve Kibana deprecation issues' ); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx index d3c92625c7a34..bbb8b049ec2b8 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx @@ -118,9 +118,11 @@ describe('Overview - Fix deprecation issues step - Elasticsearch deprecations', testBed = await setupOverviewPage(); }); - const { component, exists } = testBed; + const { component, find } = testBed; component.update(); - expect(exists('esRequestErrorIconTip')).toBe(true); + expect(find('loadingIssuesError').text()).toBe( + 'Could not retrieve Elasticsearch deprecation issues.' + ); }); test('handles unauthorized error', async () => { @@ -136,9 +138,11 @@ describe('Overview - Fix deprecation issues step - Elasticsearch deprecations', testBed = await setupOverviewPage(); }); - const { component, exists } = testBed; + const { component, find } = testBed; component.update(); - expect(exists('unauthorizedErrorIconTip')).toBe(true); + expect(find('loadingIssuesError').text()).toBe( + 'You are not authorized to view Elasticsearch deprecation issues.' + ); }); test('handles partially upgraded error', async () => { @@ -157,9 +161,11 @@ describe('Overview - Fix deprecation issues step - Elasticsearch deprecations', testBed = await setupOverviewPage({ isReadOnlyMode: false }); }); - const { component, exists } = testBed; + const { component, find } = testBed; component.update(); - expect(exists('partiallyUpgradedErrorIconTip')).toBe(true); + expect(find('loadingIssuesError').text()).toBe( + 'Upgrade Kibana to the same version as your Elasticsearch cluster. One or more nodes in the cluster is running a different version than Kibana.' + ); }); test('handles upgrade error', async () => { @@ -178,9 +184,9 @@ describe('Overview - Fix deprecation issues step - Elasticsearch deprecations', testBed = await setupOverviewPage({ isReadOnlyMode: false }); }); - const { component, exists } = testBed; + const { component, find } = testBed; component.update(); - expect(exists('upgradedErrorIconTip')).toBe(true); + expect(find('loadingIssuesError').text()).toBe('All Elasticsearch nodes have been upgraded.'); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx index 4c54f5c6932c6..3f72542dc33bf 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx @@ -124,9 +124,11 @@ describe('Overview - Fix deprecation issues step - Kibana deprecations', () => { }); }); - const { component, exists } = testBed; + const { component, find } = testBed; component.update(); - expect(exists('kibanaRequestErrorIconTip')).toBe(true); + expect(find('loadingIssuesError').text()).toBe( + 'Could not retrieve Kibana deprecation issues.' + ); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 7d0f3f49f2ee5..873ac726cd537 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -8,6 +8,8 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SavedObject, SavedObjectAttributes } from 'src/core/public'; +export type DeprecationSource = 'Kibana' | 'Elasticsearch'; + export enum ReindexStep { // Enum values are spaced out by 10 to give us room to insert steps in between. created = 0, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecation_errors.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecation_errors.tsx deleted file mode 100644 index 5e3c7a5fe6cef..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecation_errors.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { EuiCallOut } from '@elastic/eui'; - -import { ResponseError } from '../../lib/api'; -import { getEsDeprecationError } from '../../lib/get_es_deprecation_error'; -interface Props { - error: ResponseError; -} - -export const EsDeprecationErrors: React.FunctionComponent = ({ error }) => { - const { code: errorType, message } = getEsDeprecationError(error); - - switch (errorType) { - case 'unauthorized_error': - return ( - - ); - case 'partially_upgraded_error': - return ( - - ); - case 'upgraded_error': - return ; - case 'request_error': - default: - return ( - - {error.message} - - ); - } -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 5ce37e2e43815..640aee9a5dac3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -14,9 +14,9 @@ import { i18n } from '@kbn/i18n'; import { EnrichedDeprecationInfo } from '../../../../common/types'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; +import { getEsDeprecationError } from '../../lib/get_es_deprecation_error'; +import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { EsDeprecationsTable } from './es_deprecations_table'; -import { EsDeprecationErrors } from './es_deprecation_errors'; -import { NoDeprecationsPrompt, DeprecationCount } from '../shared'; const getDeprecationCountByLevel = (deprecations: EnrichedDeprecationInfo[]) => { const criticalDeprecations: EnrichedDeprecationInfo[] = []; @@ -86,7 +86,12 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { }, [api, isLoading, isInitialRequest]); if (error) { - return ; + return ( + + ); } if (isLoading) { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index aac563aa8d0bb..8158f8462da1e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -8,14 +8,14 @@ import React, { useEffect, useState, useCallback, useMemo } from 'react'; import uuid from 'uuid'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut, EuiEmptyPrompt } from '@elastic/eui'; +import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import type { DomainDeprecationDetails } from 'kibana/public'; import { SectionLoading, GlobalFlyout } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; -import { NoDeprecationsPrompt, DeprecationCount } from '../shared'; +import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { KibanaDeprecationsTable } from './kibana_deprecations_table'; import { DeprecationDetailsFlyout, @@ -67,15 +67,6 @@ const i18nTexts = { pluginIds: pluginIds.join(', '), }, }), - requestErrorTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.requestErrorTitle', { - defaultMessage: 'Could not retrieve Kibana deprecation issues', - }), - requestErrorDescription: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecationErrors.requestErrorDescription', - { - defaultMessage: 'Check the Kibana server logs for errors.', - } - ), }; export interface DeprecationResolutionState { @@ -253,15 +244,8 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) getAllDeprecations(); }, [deprecations, getAllDeprecations]); - if (kibanaDeprecations && kibanaDeprecations.length === 0) { - return ( - - history.push('/overview')} - /> - - ); + if (error) { + return ; } if (isLoading) { @@ -272,63 +256,53 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) ); } - if (kibanaDeprecations?.length) { + if (kibanaDeprecations?.length === 0) { return ( -
- - - - - - - {kibanaDeprecationErrors.length > 0 && ( - <> - -

{i18nTexts.getKibanaDeprecationErrorDescription(kibanaDeprecationErrors)}

-
- - - - )} - - + history.push('/overview')} /> -
+ ); } - if (error) { - return ( - + - {i18nTexts.requestErrorTitle}

} - body={

{i18nTexts.requestErrorDescription}

} + - - ); - } - - return null; + + + + + {kibanaDeprecationErrors.length > 0 && ( + <> + +

{i18nTexts.getKibanaDeprecationErrorDescription(kibanaDeprecationErrors)}

+
+ + + + )} + + +

+ ); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss deleted file mode 100644 index 92c92d96c31a2..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/_es_stats_error.scss +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Used for having the EuiPopover Icon for errors shown next to the title without - * having to resort to wrapping everything with EuiFlexGroups. - */ -.upgWarningIcon { - margin-left: $euiSizeS; -} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx index d5b94b89f5443..084e4528694dd 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx @@ -11,7 +11,9 @@ import { EuiCard, EuiStat, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic import { i18n } from '@kbn/i18n'; import { reactRouterNavigate } from '../../../../../shared_imports'; +import { DeprecationSource } from '../../../../../../common/types'; import { getDeprecationsUpperLimit } from '../../../../lib/utils'; +import { LoadingIssuesError } from './loading_issues_error'; import { NoDeprecationIssues } from './no_deprecation_issues'; import './_deprecation_issues_panel.scss'; @@ -33,12 +35,12 @@ const i18nTexts = { interface Props { 'data-test-subj': string; - deprecationSource: string; + deprecationSource: DeprecationSource; linkUrl: string; criticalDeprecationsCount: number; warningDeprecationsCount: number; isLoading: boolean; - errorMessage?: JSX.Element | null; + errorMessage?: JSX.Element | string | null; setIsFixed: (isFixed: boolean) => void; } @@ -70,17 +72,14 @@ export const DeprecationIssuesPanel = (props: Props) => { data-test-subj={props['data-test-subj']} className="upgDeprecationIssuesPanel" layout="horizontal" - title={ - <> - {deprecationSource} - {hasError && errorMessage} - - } + title={deprecationSource} {...(!hasNoIssues && reactRouterNavigate(history, linkUrl))} > - {hasNoIssues ? ( + {hasError ? ( + {errorMessage} + ) : hasNoIssues ? ( ) : ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_deprecation_issues_panel.tsx similarity index 84% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_deprecation_issues_panel.tsx index 89860d5b58be4..b4258ababc92e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_deprecation_issues_panel.tsx @@ -8,14 +8,14 @@ import React, { FunctionComponent } from 'react'; import { useAppContext } from '../../../../app_context'; -import { EsStatsErrors } from './es_stats_error'; +import { getEsDeprecationError } from '../../../../lib/get_es_deprecation_error'; import { DeprecationIssuesPanel } from './deprecation_issues_panel'; interface Props { setIsFixed: (isFixed: boolean) => void; } -export const ElasticsearchDeprecationStats: FunctionComponent = ({ setIsFixed }) => { +export const EsDeprecationIssuesPanel: FunctionComponent = ({ setIsFixed }) => { const { services: { api }, } = useAppContext(); @@ -29,7 +29,7 @@ export const ElasticsearchDeprecationStats: FunctionComponent = ({ setIsF esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical === false) ?.length ?? 0; - const errorMessage = error && ; + const errorMessage = error && getEsDeprecationError(error).message; return ( = ({ error }) => { - let iconContent: React.ReactNode; - - const { code: errorType, message } = getEsDeprecationError(error); - - switch (errorType) { - case 'unauthorized_error': - iconContent = ( - - ); - break; - - case 'partially_upgraded_error': - iconContent = ( - - ); - break; - - case 'upgraded_error': - iconContent = ( - - ); - break; - - case 'request_error': - default: - iconContent = ( - - ); - } - - return {iconContent}; -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/index.ts index fe3a0dd2ceaff..a2a3219002719 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/index.ts @@ -5,5 +5,5 @@ * 2.0. */ -export { ElasticsearchDeprecationStats } from './es_stats'; -export { KibanaDeprecationStats } from './kibana_stats'; +export { EsDeprecationIssuesPanel } from './es_deprecation_issues_panel'; +export { KibanaDeprecationIssuesPanel } from './kibana_deprecation_issues_panel'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_deprecation_issues_panel.tsx similarity index 77% rename from x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_stats.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_deprecation_issues_panel.tsx index 891ccc01dcd40..b0aa7b592e3a1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/kibana_deprecation_issues_panel.tsx @@ -6,7 +6,6 @@ */ import React, { FunctionComponent, useEffect, useState } from 'react'; -import { EuiIconTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { DomainDeprecationDetails } from 'kibana/public'; @@ -17,7 +16,7 @@ interface Props { setIsFixed: (isFixed: boolean) => void; } -export const KibanaDeprecationStats: FunctionComponent = ({ setIsFixed }) => { +export const KibanaDeprecationIssuesPanel: FunctionComponent = ({ setIsFixed }) => { const { services: { core: { deprecations }, @@ -53,20 +52,11 @@ export const KibanaDeprecationStats: FunctionComponent = ({ setIsFixed }) const warningDeprecationsCount = kibanaDeprecations?.filter((deprecation) => deprecation.level === 'warning')?.length ?? 0; - const errorMessage = error && ( - - ); + const errorMessage = + error && + i18n.translate('xpack.upgradeAssistant.deprecationStats.loadingErrorMessage', { + defaultMessage: 'Could not retrieve Kibana deprecation issues.', + }); return ( ( + + + + + + + {children} + + +); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx index d4ecccdd5dc15..b061ab5ea2d4d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx @@ -13,7 +13,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import type { OverviewStepProps } from '../../types'; -import { ElasticsearchDeprecationStats, KibanaDeprecationStats } from './components'; +import { EsDeprecationIssuesPanel, KibanaDeprecationIssuesPanel } from './components'; const i18nTexts = { reviewStepTitle: i18n.translate('xpack.upgradeAssistant.overview.fixIssuesStepTitle', { @@ -43,11 +43,11 @@ const FixIssuesStep: FunctionComponent = ({ setIsComplete }) => { return ( - + - + ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecations_page_loading_error.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecations_page_loading_error.tsx new file mode 100644 index 0000000000000..01cf950abbc31 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecations_page_loading_error.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { EuiPageContent, EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { DeprecationSource } from '../../../../common/types'; + +interface Props { + deprecationSource: DeprecationSource; + message?: string; +} + +export const DeprecationsPageLoadingError: FunctionComponent = ({ + deprecationSource, + message, +}) => ( + + + {i18n.translate('xpack.upgradeAssistant.deprecationsPageLoadingError.title', { + defaultMessage: 'Could not retrieve {deprecationSource} deprecation issues', + values: { deprecationSource }, + })} + + } + body={message} + /> + +); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts index 9464b5ecb98ca..ef7916f6e8d17 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts @@ -8,3 +8,4 @@ export { NoDeprecationsPrompt } from './no_deprecations'; export { DeprecationCount } from './deprecation_count'; export { DeprecationBadge } from './deprecation_badge'; +export { DeprecationsPageLoadingError } from './deprecations_page_loading_error'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts index 85cfd2a3fd16c..889568fb7a412 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts @@ -12,7 +12,7 @@ const i18nTexts = { permissionsError: i18n.translate( 'xpack.upgradeAssistant.esDeprecationErrors.permissionsErrorMessage', { - defaultMessage: 'You are not authorized to view Elasticsearch deprecations.', + defaultMessage: 'You are not authorized to view Elasticsearch deprecation issues.', } ), partiallyUpgradedWarning: i18n.translate( @@ -29,7 +29,7 @@ const i18nTexts = { } ), loadingError: i18n.translate('xpack.upgradeAssistant.esDeprecationErrors.loadingErrorMessage', { - defaultMessage: 'Could not retrieve Elasticsearch deprecations.', + defaultMessage: 'Could not retrieve Elasticsearch deprecation issues.', }), }; diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/es_deprecations.ts b/x-pack/test/api_integration/apis/upgrade_assistant/es_deprecations.ts new file mode 100644 index 0000000000000..aea003a317963 --- /dev/null +++ b/x-pack/test/api_integration/apis/upgrade_assistant/es_deprecations.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const security = getService('security'); + + describe('Elasticsearch deprecations', () => { + describe('GET /api/upgrade_assistant/es_deprecations', () => { + it('handles auth error', async () => { + const ROLE_NAME = 'authErrorRole'; + const USER_NAME = 'authErrorUser'; + const USER_PASSWORD = 'password'; + + try { + await security.role.create(ROLE_NAME, {}); + await security.user.create(USER_NAME, { + password: USER_PASSWORD, + roles: [ROLE_NAME], + }); + + await supertestWithoutAuth + .get('/api/upgrade_assistant/es_deprecations') + .auth(USER_NAME, USER_PASSWORD) + .set('kbn-xsrf', 'kibana') + .send() + .expect(403); + } finally { + await security.role.delete(ROLE_NAME); + await security.user.delete(USER_NAME); + } + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/index.ts b/x-pack/test/api_integration/apis/upgrade_assistant/index.ts index ddb71c59423ba..8d753dd661f5f 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/index.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/index.ts @@ -11,5 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('Upgrade Assistant', () => { loadTestFile(require.resolve('./upgrade_assistant')); loadTestFile(require.resolve('./cloud_backup_status')); + loadTestFile(require.resolve('./es_deprecations')); }); } From 8e84b09f6f92978080e634cb919ac682507bb3d9 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 22 Sep 2021 08:44:06 +0200 Subject: [PATCH 39/93] Change count poll time to 15s (#112669) --- x-pack/plugins/upgrade_assistant/common/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index fa55771b003d4..c037e2407ab04 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -35,4 +35,4 @@ export const DEPRECATION_LOGS_INDEX = '.logs-deprecation.elasticsearch-default'; export const DEPRECATION_LOGS_INDEX_PATTERN = '.logs-deprecation.elasticsearch-default'; export const CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS = 60000; -export const DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS = 60000; +export const DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS = 15000; From 7f991915f118e56b6aef0753b2ede730109e0599 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 23 Sep 2021 15:49:25 +0200 Subject: [PATCH 40/93] [Upgrade Assistant] Add permissions check to logs step (#112420) --- .../helpers/setup_environment.tsx | 42 ++++++---- .../fix_logs_step/fix_logs_step.test.tsx | 42 +++++++++- .../public/application/app.tsx | 21 ++--- .../deprecations_count_checkpoint.tsx | 3 +- .../overview/fix_logs_step/fix_logs_step.tsx | 62 ++++++++++++-- .../public/shared_imports.ts | 6 ++ .../upgrade_assistant/server/plugin.ts | 7 +- .../upgrade_assistant/server/routes/app.ts | 80 +++++++++++++++++++ .../server/routes/register_routes.ts | 2 + .../server/shared_imports.ts | 1 + .../plugins/upgrade_assistant/server/types.ts | 3 + .../apis/upgrade_assistant/index.ts | 1 + .../apis/upgrade_assistant/privileges.ts | 58 ++++++++++++++ 13 files changed, 294 insertions(+), 34 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/app.ts create mode 100644 x-pack/test/api_integration/apis/upgrade_assistant/privileges.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx index 887672e0bb6cd..88beb138d58c7 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx @@ -15,6 +15,7 @@ import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { MAJOR_VERSION } from '../../../common/constants'; import { HttpSetup } from 'src/core/public'; +import { AuthorizationContext, Authorization, Privileges } from '../../../public/shared_imports'; import { AppContextProvider } from '../../../public/application/app_context'; import { apiService } from '../../../public/application/lib/api'; import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; @@ -29,23 +30,34 @@ const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); export const kibanaVersion = new SemVer(MAJOR_VERSION); -export const WithAppDependencies = (Comp: any, overrides: Record = {}) => ( - props: Record -) => { - apiService.setup((mockHttpClient as unknown) as HttpSetup); - breadcrumbService.setup(() => ''); - - const appContextMock = (getAppContextMock() as unknown) as AppDependencies; - - return ( - - - - - - ); +const createAuthorizationContextValue = (privileges: Privileges) => { + return { + isLoading: false, + privileges: privileges ?? { hasAllPrivileges: false, missingPrivileges: {} }, + } as Authorization; }; +export const WithAppDependencies = + (Comp: any, { privileges, ...overrides }: Record = {}) => + (props: Record) => { + apiService.setup(mockHttpClient as unknown as HttpSetup); + breadcrumbService.setup(() => ''); + + const appContextMock = getAppContextMock() as unknown as AppDependencies; + + return ( + + + + + + + + ); + }; + export const setupEnvironment = () => { const { server, setServerAsync, httpRequestsMockHelpers } = initHttpRequests(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index 6da9612272992..7f58b36d29c36 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -22,10 +22,13 @@ jest.mock('../../../../public/application/lib/logs_checkpoint', () => { }); import { DeprecationLoggingStatus } from '../../../../common/types'; -import { DEPRECATION_LOGS_SOURCE_ID } from '../../../../common/constants'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; import { setupEnvironment, advanceTime } from '../../helpers'; -import { DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS } from '../../../../common/constants'; +import { + DEPRECATION_LOGS_INDEX, + DEPRECATION_LOGS_SOURCE_ID, + DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS, +} from '../../../../common/constants'; const getLoggingResponse = (toggle: boolean): DeprecationLoggingStatus => ({ isDeprecationLogIndexingEnabled: toggle, @@ -389,4 +392,39 @@ describe('Overview - Fix deprecation logs step', () => { expect(exists('apiCompatibilityNoteTitle')).toBe(true); }); }); + + describe('Privileges check', () => { + test(`permissions warning callout is hidden if user has the right privileges`, async () => { + const { exists } = testBed; + + // Index privileges warning callout should not be shown + expect(exists('noIndexPermissionsCallout')).toBe(false); + // Analyze logs and Resolve logs sections should be shown + expect(exists('externalLinksTitle')).toBe(true); + expect(exists('deprecationsCountTitle')).toBe(true); + }); + + test(`doesn't show analyze and resolve logs if it doesn't have the right privileges`, async () => { + await act(async () => { + testBed = await setupOverviewPage({ + privileges: { + hasAllPrivileges: false, + missingPrivileges: { + index: [DEPRECATION_LOGS_INDEX], + }, + }, + }); + }); + + const { exists, component } = testBed; + + component.update(); + + // No index privileges warning callout should be shown + expect(exists('noIndexPermissionsCallout')).toBe(true); + // Analyze logs and Resolve logs sections should be hidden + expect(exists('externalLinksTitle')).toBe(false); + expect(exists('deprecationsCountTitle')).toBe(false); + }); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index 0d32d1b661b84..be2092b46a79a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -10,8 +10,9 @@ import { Router, Switch, Route, Redirect } from 'react-router-dom'; import { ScopedHistory } from 'src/core/public'; import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; -import { APP_WRAPPER_CLASS, GlobalFlyout } from '../shared_imports'; +import { APP_WRAPPER_CLASS, GlobalFlyout, AuthorizationProvider } from '../shared_imports'; import { AppDependencies } from '../types'; +import { API_BASE_PATH } from '../../common/constants'; import { AppContextProvider, useAppContext } from './app_context'; import { EsDeprecations, ComingSoonPrompt, KibanaDeprecations, Overview } from './components'; @@ -46,18 +47,20 @@ export const AppWithRouter = ({ history }: { history: ScopedHistory }) => { export const RootComponent = (dependencies: AppDependencies) => { const { history, - core: { i18n, application }, + core: { i18n, application, http }, } = dependencies.services; return ( - - - - - - - + + + + + + + + + ); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx index 244583e9154c1..9717918e25a6d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -30,8 +30,7 @@ const i18nTexts = { /> ), calloutBody: i18n.translate('xpack.upgradeAssistant.overview.verifyChanges.calloutBody', { - defaultMessage: - 'Reset the counter after making changes and continue monitoring to verify that you are no longer using deprecated APIs.', + defaultMessage: `After making changes, reset the counter and continue monitoring to verify you're no longer using deprecated features.`, }), loadingError: i18n.translate('xpack.upgradeAssistant.overview.verifyChanges.loadingError', { defaultMessage: 'An error occurred while retrieving the count of deprecation logs', diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index d110661ad7b89..ee0935e102f9c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -4,12 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import React, { FunctionComponent, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiText, EuiSpacer, EuiPanel, EuiLink, EuiCallOut } from '@elastic/eui'; +import { EuiText, EuiSpacer, EuiPanel, EuiLink, EuiCallOut, EuiCode } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import { useAppContext } from '../../../app_context'; @@ -19,6 +18,8 @@ import { useDeprecationLogging } from './use_deprecation_logging'; import { DeprecationLoggingToggle } from './deprecation_logging_toggle'; import { loadLogsCheckpoint, saveLogsCheckpoint } from '../../../lib/logs_checkpoint'; import type { OverviewStepProps } from '../../types'; +import { DEPRECATION_LOGS_INDEX } from '../../../../../common/constants'; +import { WithPrivileges, MissingPrivileges } from '../../../../shared_imports'; const i18nTexts = { identifyStepTitle: i18n.translate('xpack.upgradeAssistant.overview.identifyStepTitle', { @@ -71,13 +72,40 @@ const i18nTexts = { 'Go to your logs directory to view the deprecation logs or enable log collecting to see them in the UI.', } ), + deniedPrivilegeTitle: i18n.translate( + 'xpack.upgradeAssistant.overview.deprecationLogs.deniedPrivilegeTitle', + { + defaultMessage: 'You require index privileges to analyze the deprecation logs', + } + ), + deniedPrivilegeDescription: (privilegesMissing: MissingPrivileges) => ( + // NOTE: hardcoding the missing privilege because the WithPrivileges HOC + // doesnt provide a way to retrieve which specific privileges an index + // is missing. + {privilegesMissing?.index?.join(', ')} + ), + privilegesCount: privilegesMissing?.index?.length, + }} + /> + ), }; interface Props { setIsComplete: OverviewStepProps['setIsComplete']; + hasPrivileges: boolean; + privilegesMissing: MissingPrivileges; } -const FixLogsStep: FunctionComponent = ({ setIsComplete }) => { +const FixLogsStep: FunctionComponent = ({ + setIsComplete, + hasPrivileges, + privilegesMissing, +}) => { const state = useDeprecationLogging(); const { services: { @@ -123,7 +151,21 @@ const FixLogsStep: FunctionComponent = ({ setIsComplete }) => { )} - {state.isDeprecationLogIndexingEnabled && ( + {!hasPrivileges && state.isDeprecationLogIndexingEnabled && ( + <> + + +

{i18nTexts.deniedPrivilegeDescription(privilegesMissing)}

+
+ + )} + + {hasPrivileges && state.isDeprecationLogIndexingEnabled && ( <> @@ -168,6 +210,16 @@ export const getFixLogsStep = ({ isComplete, setIsComplete }: OverviewStepProps) status, title: i18nTexts.identifyStepTitle, 'data-test-subj': `fixLogsStep-${status}`, - children: , + children: ( + + {({ hasPrivileges, privilegesMissing, isLoading }) => ( + + )} + + ), }; }; diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index 6fee29cf12938..1d0b1ae51f30f 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -14,6 +14,12 @@ export { UseRequestResponse, SectionLoading, GlobalFlyout, + WithPrivileges, + Privileges, + MissingPrivileges, + AuthorizationProvider, + AuthorizationContext, + Authorization, } from '../../../../src/plugins/es_ui_shared/public/'; export { Storage } from '../../../../src/plugins/kibana_utils/public'; diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index 800aeecc57d55..2062cf982d15f 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -19,6 +19,7 @@ import { SecurityPluginStart } from '../../security/server'; import { InfraPluginSetup } from '../../infra/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; +import { SecurityPluginSetup } from '../../security/server'; import { LicensingPluginSetup } from '../../licensing/server'; import { DEPRECATION_LOGS_SOURCE_ID, DEPRECATION_LOGS_INDEX } from '../common/constants'; @@ -42,6 +43,7 @@ interface PluginsSetup { licensing: LicensingPluginSetup; features: FeaturesPluginSetup; infra: InfraPluginSetup; + security?: SecurityPluginSetup; } interface PluginsStart { @@ -76,7 +78,7 @@ export class UpgradeAssistantServerPlugin implements Plugin { setup( { http, getStartServices, savedObjects }: CoreSetup, - { usageCollection, features, licensing, infra }: PluginsSetup + { usageCollection, features, licensing, infra, security }: PluginsSetup ) { this.licensing = licensing; @@ -129,6 +131,9 @@ export class UpgradeAssistantServerPlugin implements Plugin { lib: { handleEsError, }, + config: { + isSecurityEnabled: () => security !== undefined && security.license.isEnabled(), + }, }; // Initialize version service with current kibana version diff --git a/x-pack/plugins/upgrade_assistant/server/routes/app.ts b/x-pack/plugins/upgrade_assistant/server/routes/app.ts new file mode 100644 index 0000000000000..682dc83410f81 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/app.ts @@ -0,0 +1,80 @@ +/* + * 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 { API_BASE_PATH, DEPRECATION_LOGS_INDEX } from '../../common/constants'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { Privileges } from '../shared_imports'; +import { RouteDependencies } from '../types'; + +const extractMissingPrivileges = ( + privilegesObject: { [key: string]: Record } = {} +): string[] => + Object.keys(privilegesObject).reduce((privileges: string[], privilegeName: string): string[] => { + if (Object.values(privilegesObject[privilegeName]).some((e) => !e)) { + privileges.push(privilegeName); + } + return privileges; + }, []); + +export function registerAppRoutes({ + router, + lib: { handleEsError }, + config: { isSecurityEnabled }, +}: RouteDependencies) { + router.get( + { + path: `${API_BASE_PATH}/privileges`, + validate: false, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { client }, + }, + }, + request, + response + ) => { + const privilegesResult: Privileges = { + hasAllPrivileges: true, + missingPrivileges: { + index: [], + }, + }; + + if (!isSecurityEnabled()) { + return response.ok({ body: privilegesResult }); + } + + try { + const { + body: { has_all_requested: hasAllPrivileges, index }, + } = await client.asCurrentUser.security.hasPrivileges({ + body: { + index: [ + { + names: [DEPRECATION_LOGS_INDEX], + privileges: ['read'], + }, + ], + }, + }); + + if (!hasAllPrivileges) { + privilegesResult.missingPrivileges.index = extractMissingPrivileges(index); + } + + privilegesResult.hasAllPrivileges = hasAllPrivileges; + return response.ok({ body: privilegesResult }); + } catch (error) { + return handleEsError({ error, response }); + } + } + ) + ); +} diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index 813b25c4a79d0..8b63233a124a7 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -7,6 +7,7 @@ import { RouteDependencies } from '../types'; +import { registerAppRoutes } from './app'; import { registerCloudBackupStatusRoutes } from './cloud_backup_status'; import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; @@ -18,6 +19,7 @@ import { ReindexWorker } from '../lib/reindexing'; import { registerUpgradeStatusRoute } from './status'; export function registerRoutes(dependencies: RouteDependencies, getWorker: () => ReindexWorker) { + registerAppRoutes(dependencies); registerCloudBackupStatusRoutes(dependencies); registerESDeprecationRoutes(dependencies); registerDeprecationLoggingRoutes(dependencies); diff --git a/x-pack/plugins/upgrade_assistant/server/shared_imports.ts b/x-pack/plugins/upgrade_assistant/server/shared_imports.ts index 7f55d189457c7..3193c0b4b54a0 100644 --- a/x-pack/plugins/upgrade_assistant/server/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/server/shared_imports.ts @@ -6,3 +6,4 @@ */ export { handleEsError } from '../../../../src/plugins/es_ui_shared/server'; +export { Privileges } from '../../../../src/plugins/es_ui_shared/common'; diff --git a/x-pack/plugins/upgrade_assistant/server/types.ts b/x-pack/plugins/upgrade_assistant/server/types.ts index 09272d270333e..376514c59d494 100644 --- a/x-pack/plugins/upgrade_assistant/server/types.ts +++ b/x-pack/plugins/upgrade_assistant/server/types.ts @@ -21,4 +21,7 @@ export interface RouteDependencies { lib: { handleEsError: typeof handleEsError; }; + config: { + isSecurityEnabled: () => boolean; + }; } diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/index.ts b/x-pack/test/api_integration/apis/upgrade_assistant/index.ts index 8d753dd661f5f..f6b231f038817 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/index.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/index.ts @@ -11,6 +11,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('Upgrade Assistant', () => { loadTestFile(require.resolve('./upgrade_assistant')); loadTestFile(require.resolve('./cloud_backup_status')); + loadTestFile(require.resolve('./privileges')); loadTestFile(require.resolve('./es_deprecations')); }); } diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/privileges.ts b/x-pack/test/api_integration/apis/upgrade_assistant/privileges.ts new file mode 100644 index 0000000000000..c5c00c9a33685 --- /dev/null +++ b/x-pack/test/api_integration/apis/upgrade_assistant/privileges.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; +import { DEPRECATION_LOGS_INDEX } from '../../../../plugins/upgrade_assistant/common/constants'; + +export default function ({ getService }: FtrProviderContext) { + const security = getService('security'); + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + describe('Privileges', () => { + describe('GET /api/upgrade_assistant/privileges', () => { + it('User with with index privileges', async () => { + const { body } = await supertest + .get('/api/upgrade_assistant/privileges') + .set('kbn-xsrf', 'kibana') + .expect(200); + + expect(body.hasAllPrivileges).to.be(true); + expect(body.missingPrivileges.index.length).to.be(0); + }); + + it('User without index privileges', async () => { + const ROLE_NAME = 'test_role'; + const USER_NAME = 'test_user'; + const USER_PASSWORD = 'test_user'; + + try { + await security.role.create(ROLE_NAME, {}); + await security.user.create(USER_NAME, { + password: USER_PASSWORD, + roles: [ROLE_NAME], + }); + + const { body } = await supertestWithoutAuth + .get('/api/upgrade_assistant/privileges') + .auth(USER_NAME, USER_PASSWORD) + .set('kbn-xsrf', 'kibana') + .send() + .expect(200); + + expect(body.hasAllPrivileges).to.be(false); + expect(body.missingPrivileges.index[0]).to.be(DEPRECATION_LOGS_INDEX); + } finally { + await security.role.delete(ROLE_NAME); + await security.user.delete(USER_NAME); + } + }); + }); + }); +} From 1804c4dcc98bc496ec309030cd09407c2272ddf1 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 23 Sep 2021 11:32:08 -0400 Subject: [PATCH 41/93] [Upgrade Assistant] Refactor telemetry (#112177) --- .../schema/xpack_plugins.json | 38 ---- x-pack/plugins/upgrade_assistant/README.md | 27 ++- .../plugins/upgrade_assistant/common/types.ts | 29 --- .../index_settings/flyout.tsx | 16 +- .../deprecation_types/ml_snapshots/flyout.tsx | 8 + .../checklist_step.test.tsx.snap | 4 +- .../reindex/flyout/checklist_step.tsx | 22 ++- .../deprecation_types/reindex/table_row.tsx | 21 +- .../reindex/use_reindex_state.tsx | 4 - .../es_deprecations/es_deprecations.tsx | 22 +-- .../deprecation_details_flyout.tsx | 11 +- .../kibana_deprecations.tsx | 13 +- .../overview/backup_step/cloud_backup.tsx | 8 +- .../overview/backup_step/on_prem_backup.tsx | 11 +- .../deprecations_count_checkpoint.tsx | 5 +- .../overview/fix_logs_step/external_links.tsx | 27 ++- .../components/overview/overview.tsx | 13 +- .../public/application/lib/api.ts | 20 -- .../public/application/lib/ui_metric.ts | 49 +++++ .../upgrade_assistant/public/plugin.ts | 10 +- .../plugins/upgrade_assistant/public/types.ts | 2 + .../lib/telemetry/es_ui_open_apis.test.ts | 48 ----- .../server/lib/telemetry/es_ui_open_apis.ts | 57 ------ .../lib/telemetry/es_ui_reindex_apis.test.ts | 52 ----- .../lib/telemetry/es_ui_reindex_apis.ts | 63 ------ .../lib/telemetry/usage_collector.test.ts | 31 --- .../server/lib/telemetry/usage_collector.ts | 113 +---------- .../upgrade_assistant/server/plugin.ts | 3 +- .../server/routes/register_routes.ts | 2 - .../server/routes/telemetry.test.ts | 187 ------------------ .../server/routes/telemetry.ts | 64 ------ .../telemetry_saved_object_type.ts | 36 ---- 32 files changed, 207 insertions(+), 809 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index b3ca5f17634d5..ab1b77587bf78 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -7329,44 +7329,6 @@ } } } - }, - "ui_open": { - "properties": { - "elasticsearch": { - "type": "long", - "_meta": { - "description": "Number of times a user viewed the list of Elasticsearch deprecations." - } - }, - "overview": { - "type": "long", - "_meta": { - "description": "Number of times a user viewed the Overview page." - } - }, - "kibana": { - "type": "long", - "_meta": { - "description": "Number of times a user viewed the list of Kibana deprecations" - } - } - } - }, - "ui_reindex": { - "properties": { - "close": { - "type": "long" - }, - "open": { - "type": "long" - }, - "start": { - "type": "long" - }, - "stop": { - "type": "long" - } - } } } }, diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index 255eb94a0318c..6570e7f8d7617 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -226,4 +226,29 @@ This is a non-exhaustive list of different error scenarios in Upgrade Assistant. - **Error updating deprecation logging status.** Mock a `404` status code to `PUT /api/upgrade_assistant/deprecation_logging`. Alternatively, edit [this line](https://github.com/elastic/kibana/blob/545c1420c285af8f5eee56f414bd6eca735aea11/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts#L77) locally and replace `deprecation_logging` with `fake_deprecation_logging`. - **Unauthorized error fetching ES deprecations.** Mock a `403` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 403 }` - **Partially upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": false } }` -- **Upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": true } }` \ No newline at end of file +- **Upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": true } }` + +### Telemetry + +The Upgrade Assistant tracks several triggered events in the UI, using Kibana Usage Collection service's [UI counters](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#ui-counters). + +**Overview page** +- Component loaded +- Click event for "Create snapshot" button +- Click event for "View deprecation logs in Observability" link +- Click event for "Analyze logs in Discover" link +- Click event for "Reset counter" button + +**ES deprecations page** +- Component loaded +- Click events for starting and stopping reindex tasks +- Click events for upgrading or deleting a Machine Learning snapshot +- Click event for deleting a deprecated index setting + +**Kibana deprecations page** +- Component loaded +- Click event for "Quick resolve" button + +In addition to UI counters, the Upgrade Assistant has a [custom usage collector](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#custom-collector). It currently is only responsible for tracking whether the user has deprecation logging enabled or not. + +For testing instructions, refer to the [Kibana Usage Collection service README](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#testing). \ No newline at end of file diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 873ac726cd537..1614f8db6b853 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -135,32 +135,7 @@ export interface UIReindex { stop: boolean; } -export interface UpgradeAssistantTelemetrySavedObject { - ui_open: { - overview: number; - elasticsearch: number; - kibana: number; - }; - ui_reindex: { - close: number; - open: number; - start: number; - stop: number; - }; -} - export interface UpgradeAssistantTelemetry { - ui_open: { - overview: number; - elasticsearch: number; - kibana: number; - }; - ui_reindex: { - close: number; - open: number; - start: number; - stop: number; - }; features: { deprecation_logging: { enabled: boolean; @@ -168,10 +143,6 @@ export interface UpgradeAssistantTelemetry { }; } -export interface UpgradeAssistantTelemetrySavedObjectAttributes { - [key: string]: any; -} - export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; export interface DeprecationInfo { level: MIGRATION_DEPRECATION_LEVEL; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx index 24c1897fbdd02..e00edb4f3b11d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButton, EuiButtonEmpty, @@ -25,6 +26,7 @@ import { } from '@elastic/eui'; import { EnrichedDeprecationInfo, IndexSettingAction } from '../../../../../../common/types'; import type { ResponseError } from '../../../../lib/api'; +import { uiMetricService, UIM_INDEX_SETTINGS_DELETE_CLICK } from '../../../../lib/ui_metric'; import type { Status } from '../../../types'; import { DeprecationBadge } from '../../../shared'; @@ -107,6 +109,11 @@ export const RemoveIndexSettingsFlyout = ({ // Flag used to hide certain parts of the UI if the deprecation has been resolved or is in progress const isResolvable = ['idle', 'error'].includes(statusType); + const onRemoveSettings = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_INDEX_SETTINGS_DELETE_CLICK); + removeIndexSettings(index!, (correctiveAction as IndexSettingAction).deprecatedSettings); + }, [correctiveAction, index, removeIndexSettings]); + return ( <> @@ -190,12 +197,7 @@ export const RemoveIndexSettingsFlyout = ({ fill data-test-subj="deleteSettingsButton" color="danger" - onClick={() => - removeIndexSettings( - index!, - (correctiveAction as IndexSettingAction).deprecatedSettings - ) - } + onClick={onRemoveSettings} > {statusType === 'error' ? i18nTexts.retryRemoveButtonLabel diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index 40921981dfa5e..ffa661f66491d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButton, @@ -24,6 +25,11 @@ import { } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { + uiMetricService, + UIM_ML_SNAPSHOT_UPGRADE_CLICK, + UIM_ML_SNAPSHOT_DELETE_CLICK, +} from '../../../../lib/ui_metric'; import { DeprecationBadge } from '../../../shared'; import { MlSnapshotContext } from './context'; import { SnapshotState } from './use_snapshot_state'; @@ -143,11 +149,13 @@ export const FixSnapshotsFlyout = ({ const isResolved = snapshotState.status === 'complete'; const onUpgradeSnapshot = () => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_ML_SNAPSHOT_UPGRADE_CLICK); upgradeSnapshot(); closeFlyout(); }; const onDeleteSnapshot = () => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_ML_SNAPSHOT_DELETE_CLICK); deleteSnapshot(); closeFlyout(); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index 9357e7d2d9b6c..ae03647042dbc 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -42,7 +42,7 @@ exports[`ChecklistFlyout renders 1`] = ` { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_START_CLICK); + startReindex(); + }, [startReindex]); + + const onStopReindex = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_STOP_CLICK); + cancelReindex(); + }, [cancelReindex]); + return ( @@ -124,7 +140,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ /> - + @@ -142,7 +158,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ fill color={status === ReindexStatus.paused ? 'warning' : 'primary'} iconType={status === ReindexStatus.paused ? 'play' : undefined} - onClick={startReindex} + onClick={onStartReindex} isLoading={loading} disabled={loading || !hasRequiredPrivileges} > diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx index c2a14ca5be858..1059720e66a59 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx @@ -7,9 +7,15 @@ import React, { useState, useEffect, useCallback } from 'react'; import { EuiTableRowCell } from '@elastic/eui'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GlobalFlyout } from '../../../../../shared_imports'; import { useAppContext } from '../../../../app_context'; +import { + uiMetricService, + UIM_REINDEX_CLOSE_FLYOUT_CLICK, + UIM_REINDEX_OPEN_FLYOUT_CLICK, +} from '../../../../lib/ui_metric'; import { DeprecationTableColumns } from '../../../types'; import { EsDeprecationsTableCells } from '../../es_deprecations_table_cells'; import { ReindexResolutionCell } from './resolution_table_cell'; @@ -29,9 +35,6 @@ const ReindexTableRowCells: React.FunctionComponent = ({ }) => { const [showFlyout, setShowFlyout] = useState(false); const reindexState = useReindexContext(); - const { - services: { api }, - } = useAppContext(); const { addContent: addContentToGlobalFlyout, removeContent: removeContentFromGlobalFlyout } = useGlobalFlyout(); @@ -39,8 +42,8 @@ const ReindexTableRowCells: React.FunctionComponent = ({ const closeFlyout = useCallback(async () => { removeContentFromGlobalFlyout('reindexFlyout'); setShowFlyout(false); - await api.sendReindexTelemetryData({ close: true }); - }, [api, removeContentFromGlobalFlyout]); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_CLOSE_FLYOUT_CLICK); + }, [removeContentFromGlobalFlyout]); useEffect(() => { if (showFlyout) { @@ -64,13 +67,9 @@ const ReindexTableRowCells: React.FunctionComponent = ({ useEffect(() => { if (showFlyout) { - async function sendTelemetry() { - await api.sendReindexTelemetryData({ open: true }); - } - - sendTelemetry(); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_OPEN_FLYOUT_CLICK); } - }, [showFlyout, api]); + }, [showFlyout]); return ( <> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index b87a509d25a55..e1f01be2e0174 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -131,8 +131,6 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A cancelLoadingState: undefined, }); - api.sendReindexTelemetryData({ start: true }); - const { data, error } = await api.startReindexTask(indexName); if (error) { @@ -149,8 +147,6 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A }, [api, indexName, reindexState, updateStatus]); const cancelReindex = useCallback(async () => { - api.sendReindexTelemetryData({ stop: true }); - const { error } = await api.cancelReindexTask(indexName); setReindexState({ diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 640aee9a5dac3..59416cc568668 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -10,10 +10,12 @@ import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiPageHeader, EuiSpacer, EuiPageContent } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo } from '../../../../common/types'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; +import { uiMetricService, UIM_ES_DEPRECATIONS_PAGE_LOAD } from '../../lib/ui_metric'; import { getEsDeprecationError } from '../../lib/get_es_deprecation_error'; import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { EsDeprecationsTable } from './es_deprecations_table'; @@ -54,13 +56,7 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { services: { api, breadcrumbs }, } = useAppContext(); - const { - data: esDeprecations, - isLoading, - error, - resendRequest, - isInitialRequest, - } = api.useLoadEsDeprecations(); + const { data: esDeprecations, isLoading, error, resendRequest } = api.useLoadEsDeprecations(); const deprecationsCountByLevel: { warningDeprecations: number; @@ -74,16 +70,8 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { }, [breadcrumbs]); useEffect(() => { - if (isLoading === false && isInitialRequest) { - async function sendTelemetryData() { - await api.sendPageTelemetryData({ - elasticsearch: true, - }); - } - - sendTelemetryData(); - } - }, [api, isLoading, isInitialRequest]); + uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_ES_DEPRECATIONS_PAGE_LOAD); + }, []); if (error) { return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index d41b0a95e7679..6ec9ad175e112 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -5,9 +5,10 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButtonEmpty, @@ -24,6 +25,7 @@ import { EuiSpacer, } from '@elastic/eui'; +import { uiMetricService, UIM_KIBANA_QUICK_RESOLVE_CLICK } from '../../lib/ui_metric'; import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; import { DeprecationBadge } from '../shared'; @@ -134,6 +136,11 @@ export const DeprecationDetailsFlyout = ({ const isCurrent = deprecationResolutionState?.id === deprecation.id; const isResolved = isCurrent && deprecationResolutionState?.resolveDeprecationStatus === 'ok'; + const onResolveDeprecation = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_KIBANA_QUICK_RESOLVE_CLICK); + resolveDeprecation(deprecation); + }, [deprecation, resolveDeprecation]); + return ( <> @@ -225,7 +232,7 @@ export const DeprecationDetailsFlyout = ({ resolveDeprecation(deprecation)} + onClick={onResolveDeprecation} isLoading={Boolean( deprecationResolutionState?.resolveDeprecationStatus === 'in_progress' )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 8158f8462da1e..35147b2f4cf39 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -11,10 +11,12 @@ import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE } from '@kbn/analytics'; import type { DomainDeprecationDetails } from 'kibana/public'; import { SectionLoading, GlobalFlyout } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; +import { uiMetricService, UIM_KIBANA_DEPRECATIONS_PAGE_LOAD } from '../../lib/ui_metric'; import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { KibanaDeprecationsTable } from './kibana_deprecations_table'; import { @@ -116,7 +118,6 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) services: { core: { deprecations }, breadcrumbs, - api, }, } = useAppContext(); @@ -227,14 +228,8 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) ]); useEffect(() => { - async function sendTelemetryData() { - await api.sendPageTelemetryData({ - kibana: true, - }); - } - - sendTelemetryData(); - }, [api]); + uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_KIBANA_DEPRECATIONS_PAGE_LOAD); + }, []); useEffect(() => { breadcrumbs.setBreadcrumbs('kibanaDeprecations'); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx index abef34a27f30f..5d329e1b0bd26 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx @@ -9,6 +9,7 @@ import React, { useEffect } from 'react'; import moment from 'moment-timezone'; import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiLoadingContent, EuiFlexGroup, @@ -21,6 +22,7 @@ import { } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; +import { uiMetricService, UIM_BACKUP_DATA_CLOUD_CLICK } from '../../../lib/ui_metric'; interface Props { cloudSnapshotsUrl: string; @@ -133,11 +135,13 @@ export const CloudBackup: React.FunctionComponent = ({ return ( <> {statusMessage} - - + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_BACKUP_DATA_CLOUD_CLICK); + }} data-test-subj="cloudSnapshotsLink" target="_blank" iconType="popout" diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx index 2e2e2bd5ce48e..69100b36db7eb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx @@ -8,9 +8,11 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; +import { uiMetricService, UIM_BACKUP_DATA_ON_PREM_CLICK } from '../../../lib/ui_metric'; const SnapshotRestoreAppLink: React.FunctionComponent = () => { const { @@ -22,7 +24,14 @@ const SnapshotRestoreAppLink: React.FunctionComponent = () => { ?.useUrl({ page: 'snapshots' }); return ( - + // eslint-disable-next-line @elastic/eui/href-or-on-click + { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_BACKUP_DATA_ON_PREM_CLICK); + }} + data-test-subj="snapshotRestoreLink" + > ( @@ -72,6 +74,7 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ const onResetClick = () => { const now = moment().toISOString(); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_RESET_LOGS_COUNTER_CLICK); setCheckpoint(now); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx index d027b2f262e9e..69f1f14d4eb58 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx @@ -9,10 +9,17 @@ import { encode } from 'rison-node'; import React, { FunctionComponent, useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiLink, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiPanel, EuiText } from '@elastic/eui'; -import { useAppContext } from '../../../app_context'; import { DataPublicPluginStart } from '../../../../shared_imports'; +import { useAppContext } from '../../../app_context'; +import { + uiMetricService, + UIM_OBSERVABILITY_CLICK, + UIM_DISCOVER_CLICK, +} from '../../../lib/ui_metric'; + import { DEPRECATION_LOGS_INDEX_PATTERN, DEPRECATION_LOGS_SOURCE_ID, @@ -73,7 +80,14 @@ const DiscoverAppLink: FunctionComponent = ({ checkpoint }) => { }, [dataService, checkpoint, share.url.locators]); return ( - + // eslint-disable-next-line @elastic/eui/href-or-on-click + { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_DISCOVER_CLICK); + }} + data-test-subj="viewDiscoverLogs" + > = ({ checkpoint }) => { ); return ( - + // eslint-disable-next-line @elastic/eui/href-or-on-click + { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_OBSERVABILITY_CLICK); + }} + data-test-subj="viewObserveLogs" + > { kibanaVersionInfo: { nextMajor }, services: { breadcrumbs, - api, core: { docLinks }, }, plugins: { cloud }, } = useAppContext(); useEffect(() => { - async function sendTelemetryData() { - await api.sendPageTelemetryData({ - overview: true, - }); - } - - sendTelemetryData(); - }, [api]); + uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_OVERVIEW_PAGE_LOAD); + }, []); useEffect(() => { breadcrumbs.setBreadcrumbs('overview'); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index 11f59822ba1e8..ff77e10f7a8d6 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -65,16 +65,6 @@ export class ApiService { }); } - public async sendPageTelemetryData(telemetryData: { [tabName: string]: boolean }) { - const result = await this.sendRequest({ - path: `${API_BASE_PATH}/stats/ui_open`, - method: 'put', - body: JSON.stringify(telemetryData), - }); - - return result; - } - public useLoadDeprecationLogging() { return this.useRequest<{ isDeprecationLogIndexingEnabled: boolean; @@ -150,16 +140,6 @@ export class ApiService { }); } - public async sendReindexTelemetryData(telemetryData: { [key: string]: boolean }) { - const result = await this.sendRequest({ - path: `${API_BASE_PATH}/stats/ui_reindex`, - method: 'put', - body: JSON.stringify(telemetryData), - }); - - return result; - } - public async getReindexStatus(indexName: string) { return await this.sendRequest({ path: `${API_BASE_PATH}/reindex/${indexName}`, diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts new file mode 100644 index 0000000000000..394f046a8bafe --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { UiCounterMetricType } from '@kbn/analytics'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; + +export const UIM_APP_NAME = 'upgrade_assistant'; +export const UIM_ES_DEPRECATIONS_PAGE_LOAD = 'es_deprecations_page_load'; +export const UIM_KIBANA_DEPRECATIONS_PAGE_LOAD = 'kibana_deprecations_page_load'; +export const UIM_OVERVIEW_PAGE_LOAD = 'overview_page_load'; +export const UIM_REINDEX_OPEN_FLYOUT_CLICK = 'reindex_open_flyout_click'; +export const UIM_REINDEX_CLOSE_FLYOUT_CLICK = 'reindex_close_flyout_click'; +export const UIM_REINDEX_START_CLICK = 'reindex_start_click'; +export const UIM_REINDEX_STOP_CLICK = 'reindex_stop_click'; +export const UIM_BACKUP_DATA_CLOUD_CLICK = 'backup_data_cloud_click'; +export const UIM_BACKUP_DATA_ON_PREM_CLICK = 'backup_data_on_prem_click'; +export const UIM_RESET_LOGS_COUNTER_CLICK = 'reset_logs_counter_click'; +export const UIM_OBSERVABILITY_CLICK = 'observability_click'; +export const UIM_DISCOVER_CLICK = 'discover_click'; +export const UIM_ML_SNAPSHOT_UPGRADE_CLICK = 'ml_snapshot_upgrade_click'; +export const UIM_ML_SNAPSHOT_DELETE_CLICK = 'ml_snapshot_delete_click'; +export const UIM_INDEX_SETTINGS_DELETE_CLICK = 'index_settings_delete_click'; +export const UIM_KIBANA_QUICK_RESOLVE_CLICK = 'kibana_quick_resolve_click'; + +export class UiMetricService { + private usageCollection: UsageCollectionSetup | undefined; + + public setup(usageCollection: UsageCollectionSetup) { + this.usageCollection = usageCollection; + } + + private track(metricType: UiCounterMetricType, eventName: string | string[]) { + if (!this.usageCollection) { + // Usage collection might be disabled in Kibana config. + return; + } + return this.usageCollection.reportUiCounter(UIM_APP_NAME, metricType, eventName); + } + + public trackUiMetric(metricType: UiCounterMetricType, eventName: string | string[]) { + return this.track(metricType, eventName); + } +} + +export const uiMetricService = new UiMetricService(); diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index bafcae79acc13..aed21c058740f 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -11,6 +11,7 @@ import { Plugin, CoreSetup, PluginInitializerContext } from 'src/core/public'; import { apiService } from './application/lib/api'; import { breadcrumbService } from './application/lib/breadcrumbs'; +import { uiMetricService } from './application/lib/ui_metric'; import { SetupDependencies, StartDependencies, AppDependencies, ClientConfigType } from './types'; export class UpgradeAssistantUIPlugin @@ -18,7 +19,10 @@ export class UpgradeAssistantUIPlugin { constructor(private ctx: PluginInitializerContext) {} - setup(coreSetup: CoreSetup, { management, cloud, share }: SetupDependencies) { + setup( + coreSetup: CoreSetup, + { management, cloud, share, usageCollection }: SetupDependencies + ) { const { readonly, ui: { enabled: isUpgradeAssistantUiEnabled }, @@ -38,6 +42,10 @@ export class UpgradeAssistantUIPlugin defaultMessage: 'Upgrade Assistant', }); + if (usageCollection) { + uiMetricService.setup(usageCollection); + } + appRegistrar.registerApp({ id: 'upgrade_assistant', title: pluginName, diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index 4d47c10fdeec2..ace009d9c74aa 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -10,6 +10,7 @@ import { ManagementSetup } from 'src/plugins/management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SharePluginSetup } from 'src/plugins/share/public'; import { CoreStart } from 'src/core/public'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; import { BreadcrumbService } from './application/lib/breadcrumbs'; @@ -25,6 +26,7 @@ export interface SetupDependencies { management: ManagementSetup; share: SharePluginSetup; cloud?: CloudSetup; + usageCollection?: UsageCollectionSetup; } export interface StartDependencies { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts deleted file mode 100644 index caff78390b9d1..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; - -import { upsertUIOpenOption } from './es_ui_open_apis'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry SavedObject UIOpen', () => { - describe('Upsert UIOpen Option', () => { - it('call saved objects internal repository with the correct info', async () => { - const internalRepo = savedObjectsRepositoryMock.create(); - - await upsertUIOpenOption({ - overview: true, - elasticsearch: true, - kibana: true, - savedObjects: { createInternalRepository: () => internalRepo } as any, - }); - - expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(3); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - ['ui_open.overview'] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - ['ui_open.elasticsearch'] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - ['ui_open.kibana'] - ); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts deleted file mode 100644 index 3d463fe4b03ed..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SavedObjectsServiceStart } from 'src/core/server'; -import { - UIOpen, - UIOpenOption, - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, -} from '../../../common/types'; - -interface IncrementUIOpenDependencies { - uiOpenOptionCounter: UIOpenOption; - savedObjects: SavedObjectsServiceStart; -} - -async function incrementUIOpenOptionCounter({ - savedObjects, - uiOpenOptionCounter, -}: IncrementUIOpenDependencies) { - const internalRepository = savedObjects.createInternalRepository(); - - await internalRepository.incrementCounter(UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, [ - `ui_open.${uiOpenOptionCounter}`, - ]); -} - -type UpsertUIOpenOptionDependencies = UIOpen & { savedObjects: SavedObjectsServiceStart }; - -export async function upsertUIOpenOption({ - overview, - elasticsearch, - savedObjects, - kibana, -}: UpsertUIOpenOptionDependencies): Promise { - if (overview) { - await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'overview' }); - } - - if (elasticsearch) { - await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'elasticsearch' }); - } - - if (kibana) { - await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'kibana' }); - } - - return { - overview, - elasticsearch, - kibana, - }; -} diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts deleted file mode 100644 index 6a05e8a697bb8..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; -import { upsertUIReindexOption } from './es_ui_reindex_apis'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry SavedObject UIReindex', () => { - describe('Upsert UIReindex Option', () => { - it('call saved objects internal repository with the correct info', async () => { - const internalRepo = savedObjectsRepositoryMock.create(); - await upsertUIReindexOption({ - close: true, - open: true, - start: true, - stop: true, - savedObjects: { createInternalRepository: () => internalRepo } as any, - }); - - expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(4); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.close`] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.open`] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.start`] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.stop`] - ); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts deleted file mode 100644 index caee1a58a4006..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SavedObjectsServiceStart } from 'src/core/server'; -import { - UIReindex, - UIReindexOption, - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, -} from '../../../common/types'; - -interface IncrementUIReindexOptionDependencies { - uiReindexOptionCounter: UIReindexOption; - savedObjects: SavedObjectsServiceStart; -} - -async function incrementUIReindexOptionCounter({ - savedObjects, - uiReindexOptionCounter, -}: IncrementUIReindexOptionDependencies) { - const internalRepository = savedObjects.createInternalRepository(); - - await internalRepository.incrementCounter(UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, [ - `ui_reindex.${uiReindexOptionCounter}`, - ]); -} - -type UpsertUIReindexOptionDepencies = UIReindex & { savedObjects: SavedObjectsServiceStart }; - -export async function upsertUIReindexOption({ - start, - close, - open, - stop, - savedObjects, -}: UpsertUIReindexOptionDepencies): Promise { - if (close) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'close' }); - } - - if (open) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'open' }); - } - - if (start) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'start' }); - } - - if (stop) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'stop' }); - } - - return { - close, - open, - start, - stop, - }; -} diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts index 50c5b358aa5cb..34d329557f11e 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts @@ -47,26 +47,6 @@ describe('Upgrade Assistant Usage Collector', () => { }; dependencies = { usageCollection, - savedObjects: { - createInternalRepository: jest.fn().mockImplementation(() => { - return { - get: () => { - return { - attributes: { - 'ui_open.overview': 10, - 'ui_open.elasticsearch': 20, - 'ui_open.kibana': 15, - 'ui_reindex.close': 1, - 'ui_reindex.open': 4, - 'ui_reindex.start': 2, - 'ui_reindex.stop': 1, - 'ui_reindex.not_defined': 1, - }, - }; - }, - }; - }), - }, elasticsearch: { client: clusterClient, }, @@ -91,17 +71,6 @@ describe('Upgrade Assistant Usage Collector', () => { callClusterStub ); expect(upgradeAssistantStats).toEqual({ - ui_open: { - overview: 10, - elasticsearch: 20, - kibana: 15, - }, - ui_reindex: { - close: 1, - open: 4, - start: 2, - stop: 1, - }, features: { deprecation_logging: { enabled: true, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index 56932f5e54b06..c535cd14f104d 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -5,43 +5,14 @@ * 2.0. */ -import { get } from 'lodash'; -import { - ElasticsearchClient, - ElasticsearchServiceStart, - ISavedObjectsRepository, - SavedObjectsServiceStart, -} from 'src/core/server'; +import { ElasticsearchClient, ElasticsearchServiceStart } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, - UpgradeAssistantTelemetry, - UpgradeAssistantTelemetrySavedObject, - UpgradeAssistantTelemetrySavedObjectAttributes, -} from '../../../common/types'; +import { UpgradeAssistantTelemetry } from '../../../common/types'; import { isDeprecationLogIndexingEnabled, isDeprecationLoggingEnabled, } from '../es_deprecation_logging_apis'; -async function getSavedObjectAttributesFromRepo( - savedObjectsRepository: ISavedObjectsRepository, - docType: string, - docID: string -) { - try { - return ( - await savedObjectsRepository.get( - docType, - docID - ) - ).attributes; - } catch (e) { - return null; - } -} - async function getDeprecationLoggingStatusValue(esClient: ElasticsearchClient): Promise { try { const { body: loggerDeprecationCallResult } = await esClient.cluster.getSettings({ @@ -57,58 +28,14 @@ async function getDeprecationLoggingStatusValue(esClient: ElasticsearchClient): } } -export async function fetchUpgradeAssistantMetrics( - { client: esClient }: ElasticsearchServiceStart, - savedObjects: SavedObjectsServiceStart -): Promise { - const savedObjectsRepository = savedObjects.createInternalRepository(); - const upgradeAssistantSOAttributes = await getSavedObjectAttributesFromRepo( - savedObjectsRepository, - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID - ); +export async function fetchUpgradeAssistantMetrics({ + client: esClient, +}: ElasticsearchServiceStart): Promise { const deprecationLoggingStatusValue = await getDeprecationLoggingStatusValue( esClient.asInternalUser ); - const getTelemetrySavedObject = ( - upgradeAssistantTelemetrySavedObjectAttrs: UpgradeAssistantTelemetrySavedObjectAttributes | null - ): UpgradeAssistantTelemetrySavedObject => { - const defaultTelemetrySavedObject = { - ui_open: { - overview: 0, - elasticsearch: 0, - kibana: 0, - }, - ui_reindex: { - close: 0, - open: 0, - start: 0, - stop: 0, - }, - }; - - if (!upgradeAssistantTelemetrySavedObjectAttrs) { - return defaultTelemetrySavedObject; - } - - return { - ui_open: { - overview: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.overview', 0), - elasticsearch: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.elasticsearch', 0), - kibana: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.kibana', 0), - }, - ui_reindex: { - close: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.close', 0), - open: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.open', 0), - start: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.start', 0), - stop: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.stop', 0), - }, - } as UpgradeAssistantTelemetrySavedObject; - }; - return { - ...getTelemetrySavedObject(upgradeAssistantSOAttributes), features: { deprecation_logging: { enabled: deprecationLoggingStatusValue, @@ -119,14 +46,12 @@ export async function fetchUpgradeAssistantMetrics( interface Dependencies { elasticsearch: ElasticsearchServiceStart; - savedObjects: SavedObjectsServiceStart; usageCollection: UsageCollectionSetup; } export function registerUpgradeAssistantUsageCollector({ elasticsearch, usageCollection, - savedObjects, }: Dependencies) { const upgradeAssistantUsageCollector = usageCollection.makeUsageCollector({ @@ -143,34 +68,8 @@ export function registerUpgradeAssistantUsageCollector({ }, }, }, - ui_open: { - elasticsearch: { - type: 'long', - _meta: { - description: 'Number of times a user viewed the list of Elasticsearch deprecations.', - }, - }, - overview: { - type: 'long', - _meta: { - description: 'Number of times a user viewed the Overview page.', - }, - }, - kibana: { - type: 'long', - _meta: { - description: 'Number of times a user viewed the list of Kibana deprecations', - }, - }, - }, - ui_reindex: { - close: { type: 'long' }, - open: { type: 'long' }, - start: { type: 'long' }, - stop: { type: 'long' }, - }, }, - fetch: async () => fetchUpgradeAssistantMetrics(elasticsearch, savedObjects), + fetch: async () => fetchUpgradeAssistantMetrics(elasticsearch), }); usageCollection.registerCollector(upgradeAssistantUsageCollector); diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index 2062cf982d15f..717f03758f825 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -142,11 +142,10 @@ export class UpgradeAssistantServerPlugin implements Plugin { registerRoutes(dependencies, this.getWorker.bind(this)); if (usageCollection) { - getStartServices().then(([{ savedObjects: savedObjectsService, elasticsearch }]) => { + getStartServices().then(([{ elasticsearch }]) => { registerUpgradeAssistantUsageCollector({ elasticsearch, usageCollection, - savedObjects: savedObjectsService, }); }); } diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index 8b63233a124a7..002f34a489cff 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -12,7 +12,6 @@ import { registerCloudBackupStatusRoutes } from './cloud_backup_status'; import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; import { registerReindexIndicesRoutes } from './reindex_indices'; -import { registerTelemetryRoutes } from './telemetry'; import { registerUpdateSettingsRoute } from './update_index_settings'; import { registerMlSnapshotRoutes } from './ml_snapshots'; import { ReindexWorker } from '../lib/reindexing'; @@ -24,7 +23,6 @@ export function registerRoutes(dependencies: RouteDependencies, getWorker: () => registerESDeprecationRoutes(dependencies); registerDeprecationLoggingRoutes(dependencies); registerReindexIndicesRoutes(dependencies, getWorker); - registerTelemetryRoutes(dependencies); registerUpdateSettingsRoute(dependencies); registerMlSnapshotRoutes(dependencies); // Route for cloud to retrieve the upgrade status for ES and Kibana diff --git a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts deleted file mode 100644 index 578cceb702751..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { kibanaResponseFactory } from 'src/core/server'; -import { savedObjectsServiceMock } from 'src/core/server/mocks'; -import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; -import { createRequestMock } from './__mocks__/request.mock'; - -jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ - upsertUIOpenOption: jest.fn(), -})); - -jest.mock('../lib/telemetry/es_ui_reindex_apis', () => ({ - upsertUIReindexOption: jest.fn(), -})); - -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; -import { registerTelemetryRoutes } from './telemetry'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry API', () => { - let routeDependencies: any; - let mockRouter: MockRouter; - beforeEach(() => { - mockRouter = createMockRouter(); - routeDependencies = { - getSavedObjectsService: () => savedObjectsServiceMock.create(), - router: mockRouter, - }; - registerTelemetryRoutes(routeDependencies); - }); - afterEach(() => jest.clearAllMocks()); - - describe('PUT /api/upgrade_assistant/stats/ui_open', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - overview: true, - elasticsearch: false, - kibana: false, - }; - - (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_open', - })( - routeHandlerContextMock, - createRequestMock({ body: returnPayload }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - overview: true, - elasticsearch: true, - kibana: true, - }; - - (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_open', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - overview: true, - elasticsearch: true, - kibana: true, - }, - }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - (upsertUIOpenOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); - - await expect( - routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_open', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - overview: false, - }, - }), - kibanaResponseFactory - ) - ).rejects.toThrowError('scary error!'); - }); - }); - - describe('PUT /api/upgrade_assistant/stats/ui_reindex', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - close: false, - open: false, - start: true, - stop: false, - }; - - (upsertUIReindexOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_reindex', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - overview: false, - }, - }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - close: true, - open: true, - start: true, - stop: true, - }; - - (upsertUIReindexOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_reindex', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - close: true, - open: true, - start: true, - stop: true, - }, - }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - (upsertUIReindexOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); - - await expect( - routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_reindex', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - start: false, - }, - }), - kibanaResponseFactory - ) - ).rejects.toThrowError('scary error!'); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts deleted file mode 100644 index d083b38c7c240..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts +++ /dev/null @@ -1,64 +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 { schema } from '@kbn/config-schema'; -import { API_BASE_PATH } from '../../common/constants'; -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; -import { RouteDependencies } from '../types'; - -export function registerTelemetryRoutes({ router, getSavedObjectsService }: RouteDependencies) { - router.put( - { - path: `${API_BASE_PATH}/stats/ui_open`, - validate: { - body: schema.object({ - overview: schema.boolean({ defaultValue: false }), - elasticsearch: schema.boolean({ defaultValue: false }), - kibana: schema.boolean({ defaultValue: false }), - }), - }, - }, - async (ctx, request, response) => { - const { elasticsearch, overview, kibana } = request.body; - return response.ok({ - body: await upsertUIOpenOption({ - savedObjects: getSavedObjectsService(), - elasticsearch, - overview, - kibana, - }), - }); - } - ); - - router.put( - { - path: `${API_BASE_PATH}/stats/ui_reindex`, - validate: { - body: schema.object({ - close: schema.boolean({ defaultValue: false }), - open: schema.boolean({ defaultValue: false }), - start: schema.boolean({ defaultValue: false }), - stop: schema.boolean({ defaultValue: false }), - }), - }, - }, - async (ctx, request, response) => { - const { close, open, start, stop } = request.body; - return response.ok({ - body: await upsertUIReindexOption({ - savedObjects: getSavedObjectsService(), - close, - open, - start, - stop, - }), - }); - } - ); -} diff --git a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts index 42d5d339dd050..cb3fbcaef59b7 100644 --- a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts +++ b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts @@ -15,42 +15,6 @@ export const telemetrySavedObjectType: SavedObjectsType = { namespaceType: 'agnostic', mappings: { properties: { - ui_open: { - properties: { - overview: { - type: 'long', - null_value: 0, - }, - elasticsearch: { - type: 'long', - null_value: 0, - }, - kibana: { - type: 'long', - null_value: 0, - }, - }, - }, - ui_reindex: { - properties: { - close: { - type: 'long', - null_value: 0, - }, - open: { - type: 'long', - null_value: 0, - }, - start: { - type: 'long', - null_value: 0, - }, - stop: { - type: 'long', - null_value: 0, - }, - }, - }, features: { properties: { deprecation_logging: { From 38c2b1b8bd61ae86fe82a2ef972f6c92140de06b Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 27 Sep 2021 16:00:40 +0100 Subject: [PATCH 42/93] [Upgrade Assistant] Check for ML upgrade mode before enabling flyout actions (#112555) --- .../public/doc_links/doc_links_service.ts | 7 +-- .../es_deprecations/deprecations_list.test.ts | 14 ++++-- .../ml_snapshots_deprecation_flyout.test.ts | 22 +++++++++ .../helpers/http_requests.ts | 12 +++++ .../ml_snapshots/context.tsx | 4 ++ .../deprecation_types/ml_snapshots/flyout.tsx | 49 ++++++++++++++++++- .../ml_snapshots/table_row.tsx | 2 + .../es_deprecations/es_deprecations_table.tsx | 23 +++++++-- .../public/application/lib/api.ts | 9 ++++ .../server/routes/ml_snapshots.test.ts | 22 +++++++++ .../server/routes/ml_snapshots.ts | 31 ++++++++++++ 11 files changed, 183 insertions(+), 12 deletions(-) diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 6e8e620049a56..b6e640933ca08 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -288,9 +288,10 @@ export class DocLinksService { customUrls: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-configuring-url.html`, dataFrameAnalytics: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics.html`, featureImportance: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-feature-importance.html`, - outlierDetectionRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfa-finding-outliers.html#ml-dfanalytics-roc`, - regressionEvaluation: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfa-regression.html#ml-dfanalytics-regression-evaluation`, - classificationAucRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfa-classification.html#ml-dfanalytics-class-aucroc`, + outlierDetectionRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-roc`, + regressionEvaluation: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-regression-evaluation`, + classificationAucRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-class-aucroc`, + setUpgradeMode: `${ELASTICSEARCH_DOCS}ml-set-upgrade-mode.html`, }, transforms: { guide: `${ELASTICSEARCH_DOCS}transforms.html`, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index 390aeeb6d33e3..3b8a756b8e64c 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -62,19 +62,23 @@ describe('ES deprecations table', () => { const mlDeprecation = esDeprecationsMockResponse.deprecations[0]; const reindexDeprecation = esDeprecationsMockResponse.deprecations[3]; - // Since upgradeStatusMockResponse includes ML and reindex actions (which require fetching status), there will be 3 requests made - expect(server.requests.length).toBe(totalRequests + 3); - expect(server.requests[server.requests.length - 3].url).toBe( + // Since upgradeStatusMockResponse includes ML and reindex actions (which require fetching status), there will be 4 requests made + expect(server.requests.length).toBe(totalRequests + 4); + expect(server.requests[server.requests.length - 4].url).toBe( `${API_BASE_PATH}/es_deprecations` ); - expect(server.requests[server.requests.length - 2].url).toBe( + expect(server.requests[server.requests.length - 3].url).toBe( `${API_BASE_PATH}/ml_snapshots/${(mlDeprecation.correctiveAction as MlAction).jobId}/${ (mlDeprecation.correctiveAction as MlAction).snapshotId }` ); - expect(server.requests[server.requests.length - 1].url).toBe( + expect(server.requests[server.requests.length - 2].url).toBe( `${API_BASE_PATH}/reindex/${reindexDeprecation.index}` ); + + expect(server.requests[server.requests.length - 1].url).toBe( + `${API_BASE_PATH}/ml_upgrade_mode` + ); }); it('shows critical and warning deprecations count', () => { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts index bf20d52639699..6bcb3fa95985c 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts @@ -23,6 +23,7 @@ describe('Machine learning deprecation flyout', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecationsMockResponse); + httpRequestsMockHelpers.setLoadMlUpgradeModeResponse({ mlUpgradeModeEnabled: false }); httpRequestsMockHelpers.setUpgradeMlSnapshotStatusResponse({ nodeId: 'my_node', snapshotId: MOCK_SNAPSHOT_ID, @@ -131,6 +132,27 @@ describe('Machine learning deprecation flyout', () => { // Verify the upgrade button text changes expect(find('mlSnapshotDetails.upgradeSnapshotButton').text()).toEqual('Retry upgrade'); }); + + it('Disables actions if ml_upgrade_mode is enabled', async () => { + httpRequestsMockHelpers.setLoadMlUpgradeModeResponse({ mlUpgradeModeEnabled: true }); + + await act(async () => { + testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); + }); + + const { actions, exists, component } = testBed; + + component.update(); + + await actions.table.clickDeprecationRowAt('mlSnapshot', 0); + + // Shows an error callout with a docs link + expect(exists('mlSnapshotDetails.mlUpgradeModeEnabledError')).toBe(true); + expect(exists('mlSnapshotDetails.setUpgradeModeDocsLink')).toBe(true); + // Flyout actions should be hidden + expect(exists('mlSnapshotDetails.upgradeSnapshotButton')).toBe(false); + expect(exists('mlSnapshotDetails.deleteSnapshotButton')).toBe(false); + }); }); describe('delete snapshots', () => { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts index 2a3f7f5321b5b..e217ea4c5eff0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts @@ -126,6 +126,17 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setLoadMlUpgradeModeResponse = (response?: object, error?: ResponseError) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + + server.respondWith('GET', `${API_BASE_PATH}/ml_upgrade_mode`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + return { setLoadCloudBackupStatusResponse, setLoadEsDeprecationsResponse, @@ -136,6 +147,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { setDeleteMlSnapshotResponse, setUpgradeMlSnapshotStatusResponse, setLoadDeprecationLogsCountResponse, + setLoadMlUpgradeModeResponse, }; }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/context.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/context.tsx index 972d640d18c5a..3a81c7f1cc8ea 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/context.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/context.tsx @@ -12,6 +12,7 @@ import { useSnapshotState, SnapshotState } from './use_snapshot_state'; export interface MlSnapshotContext { snapshotState: SnapshotState; + mlUpgradeModeEnabled: boolean; upgradeSnapshot: () => Promise; deleteSnapshot: () => Promise; } @@ -31,12 +32,14 @@ interface Props { children: React.ReactNode; snapshotId: string; jobId: string; + mlUpgradeModeEnabled: boolean; } export const MlSnapshotsStatusProvider: React.FunctionComponent = ({ api, snapshotId, jobId, + mlUpgradeModeEnabled, children, }) => { const { updateSnapshotStatus, snapshotState, upgradeSnapshot, deleteSnapshot } = useSnapshotState( @@ -57,6 +60,7 @@ export const MlSnapshotsStatusProvider: React.FunctionComponent = ({ snapshotState, upgradeSnapshot, deleteSnapshot, + mlUpgradeModeEnabled, }} > {children} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index ffa661f66491d..2a36f3e33e83c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { METRIC_TYPE } from '@kbn/analytics'; import { @@ -32,6 +33,7 @@ import { } from '../../../../lib/ui_metric'; import { DeprecationBadge } from '../../../shared'; import { MlSnapshotContext } from './context'; +import { useAppContext } from '../../../../app_context'; import { SnapshotState } from './use_snapshot_state'; export interface FixSnapshotsFlyoutProps extends MlSnapshotContext { @@ -103,6 +105,28 @@ const i18nTexts = { defaultMessage: 'Learn more about this deprecation', } ), + upgradeModeEnabledErrorTitle: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.upgradeModeEnabledErrorTitle', + { + defaultMessage: 'Machine Learning upgrade mode is enabled', + } + ), + upgradeModeEnabledErrorDescription: (docsLink: string) => ( + + + + ), + }} + /> + ), }; const getDeleteButtonLabel = (snapshotState: SnapshotState) => { @@ -145,7 +169,13 @@ export const FixSnapshotsFlyout = ({ snapshotState, upgradeSnapshot, deleteSnapshot, + mlUpgradeModeEnabled, }: FixSnapshotsFlyoutProps) => { + const { + services: { + core: { docLinks }, + }, + } = useAppContext(); const isResolved = snapshotState.status === 'complete'; const onUpgradeSnapshot = () => { @@ -187,6 +217,23 @@ export const FixSnapshotsFlyout = ({ )} + + {mlUpgradeModeEnabled && ( + <> + +

+ {i18nTexts.upgradeModeEnabledErrorDescription(docLinks.links.ml.setUpgradeMode)} +

+
+ + + )} +

{deprecation.details}

@@ -204,7 +251,7 @@ export const FixSnapshotsFlyout = ({ - {!isResolved && ( + {!isResolved && !mlUpgradeModeEnabled && ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx index 76d99373febb3..37dddd8171c83 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/table_row.tsx @@ -21,6 +21,7 @@ const { useGlobalFlyout } = GlobalFlyout; interface TableRowProps { deprecation: EnrichedDeprecationInfo; rowFieldNames: DeprecationTableColumns[]; + mlUpgradeModeEnabled: boolean; } export const MlSnapshotsTableRowCells: React.FunctionComponent = ({ @@ -85,6 +86,7 @@ export const MlSnapshotsTableRow: React.FunctionComponent = (prop diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx index e37d8dc6f77fc..3d9b554913c5b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table.tsx @@ -26,6 +26,7 @@ import { Query, } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../common/types'; +import { useAppContext } from '../../app_context'; import { MlSnapshotsTableRow, DefaultTableRow, @@ -101,10 +102,19 @@ const cellToLabelMap = { const cellTypes = Object.keys(cellToLabelMap) as DeprecationTableColumns[]; const pageSizeOptions = PAGINATION_CONFIG.pageSizeOptions; -const renderTableRowCells = (deprecation: EnrichedDeprecationInfo) => { +const renderTableRowCells = ( + deprecation: EnrichedDeprecationInfo, + mlUpgradeModeEnabled: boolean +) => { switch (deprecation.correctiveAction?.type) { case 'mlSnapshot': - return ; + return ( + + ); case 'indexSetting': return ; @@ -146,6 +156,13 @@ export const EsDeprecationsTable: React.FunctionComponent = ({ deprecations = [], reload, }) => { + const { + services: { api }, + } = useAppContext(); + + const { data } = api.useLoadMlUpgradeMode(); + const mlUpgradeModeEnabled = !!data?.mlUpgradeModeEnabled; + const [sortConfig, setSortConfig] = useState({ isSortAscending: true, sortField: 'isCritical', @@ -291,7 +308,7 @@ export const EsDeprecationsTable: React.FunctionComponent = ({ {visibleDeprecations.map((deprecation, index) => { return ( - {renderTableRowCells(deprecation)} + {renderTableRowCells(deprecation, mlUpgradeModeEnabled)} ); })} diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index ff77e10f7a8d6..1d51510333ef4 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -160,6 +160,15 @@ export class ApiService { method: 'post', }); } + + public useLoadMlUpgradeMode() { + return this.useRequest<{ + mlUpgradeModeEnabled: boolean; + }>({ + path: `${API_BASE_PATH}/ml_upgrade_mode`, + method: 'get', + }); + } } export const apiService = new ApiService(); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts index 2e53f571ee904..995e3a46cef0e 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts @@ -175,6 +175,28 @@ describe('ML snapshots APIs', () => { }); }); + describe('GET /api/upgrade_assistant/ml_upgrade_mode', () => { + it('Retrieves ml upgrade mode', async () => { + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml.info as jest.Mock + ).mockResolvedValue({ + body: { + upgrade_mode: true, + }, + }); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/ml_upgrade_mode', + })(routeHandlerContextMock, createRequestMock({}), kibanaResponseFactory); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + mlUpgradeModeEnabled: true, + }); + }); + }); + describe('GET /api/upgrade_assistant/ml_snapshots/:jobId/:snapshotId', () => { it('returns "idle" status if saved object does not exist', async () => { ( diff --git a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts index df977c4c9a157..fa6af0f5e4228 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts @@ -300,6 +300,37 @@ export function registerMlSnapshotRoutes({ router, lib: { handleEsError } }: Rou ) ); + // Get the ml upgrade mode + router.get( + { + path: `${API_BASE_PATH}/ml_upgrade_mode`, + validate: false, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { client: esClient }, + }, + }, + request, + response + ) => { + try { + const { body: mlInfo } = await esClient.asCurrentUser.ml.info(); + + return response.ok({ + body: { + mlUpgradeModeEnabled: mlInfo.upgrade_mode, + }, + }); + } catch (e) { + return handleEsError({ error: e, response }); + } + } + ) + ); + // Delete ML model snapshot router.delete( { From 2b3a44e3c5f376af7b2306c5eede0c7229fa4565 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 27 Sep 2021 21:00:44 +0100 Subject: [PATCH 43/93] Add missing error handlers for deprecation logging route (#113109) --- .../server/routes/deprecation_logging.test.ts | 2 + .../server/routes/deprecation_logging.ts | 61 ++++++++++++------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts index 3de96832549fb..b94e75d1aedab 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts @@ -8,6 +8,7 @@ import { kibanaResponseFactory } from 'src/core/server'; import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; +import { handleEsError } from '../shared_imports'; jest.mock('../lib/es_version_precheck', () => ({ versionCheckHandlerWrapper: (a: any) => a, @@ -28,6 +29,7 @@ describe('deprecation logging API', () => { mockRouter = createMockRouter(); routeDependencies = { router: mockRouter, + lib: { handleEsError }, }; registerDeprecationLoggingRoutes(routeDependencies); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts index a0dfe0d152ad5..00116ae24a3fb 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts @@ -16,7 +16,10 @@ import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { RouteDependencies } from '../types'; import { DEPRECATION_LOGS_INDEX } from '../../common/constants'; -export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) { +export function registerDeprecationLoggingRoutes({ + router, + lib: { handleEsError }, +}: RouteDependencies) { router.get( { path: `${API_BASE_PATH}/deprecation_logging`, @@ -32,8 +35,12 @@ export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) request, response ) => { - const result = await getDeprecationLoggingStatus(client); - return response.ok({ body: result }); + try { + const result = await getDeprecationLoggingStatus(client); + return response.ok({ body: result }); + } catch (error) { + return handleEsError({ error, response }); + } } ) ); @@ -57,10 +64,14 @@ export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) request, response ) => { - const { isEnabled } = request.body as { isEnabled: boolean }; - return response.ok({ - body: await setDeprecationLogging(client, isEnabled), - }); + try { + const { isEnabled } = request.body as { isEnabled: boolean }; + return response.ok({ + body: await setDeprecationLogging(client, isEnabled), + }); + } catch (error) { + return handleEsError({ error, response }); + } } ) ); @@ -84,28 +95,32 @@ export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) request, response ) => { - const { body: indexExists } = await client.asCurrentUser.indices.exists({ - index: DEPRECATION_LOGS_INDEX, - }); + try { + const { body: indexExists } = await client.asCurrentUser.indices.exists({ + index: DEPRECATION_LOGS_INDEX, + }); - if (!indexExists) { - return response.ok({ body: { count: 0 } }); - } + if (!indexExists) { + return response.ok({ body: { count: 0 } }); + } - const { body } = await client.asCurrentUser.count({ - index: DEPRECATION_LOGS_INDEX, - body: { - query: { - range: { - '@timestamp': { - gte: request.query.from, + const { body } = await client.asCurrentUser.count({ + index: DEPRECATION_LOGS_INDEX, + body: { + query: { + range: { + '@timestamp': { + gte: request.query.from, + }, }, }, }, - }, - }); + }); - return response.ok({ body: { count: body.count } }); + return response.ok({ body: { count: body.count } }); + } catch (error) { + return handleEsError({ error, response }); + } } ) ); From ba8f56d7a68fd20eef3a5aaf950644e694c167dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 28 Sep 2021 10:26:49 +0200 Subject: [PATCH 44/93] [Upgrade Assistant] Batch reindex docs (#112960) * [UA] Added batch reindexing docs link to the ES deprecations page. Added a link from "batch reindexing" docs page to "start or resume reindex" docs page and from there to ES reindexing docs page. Also renamed "reindexing operation" to "reindexing task" for consistency. * [Upgrade Assistant] Added docs build files * Update x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com> * Update x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com> * [Upgrade Assistant] Added review suggestions and fixed eslint issues Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../batch_reindexing.asciidoc | 4 +- .../upgrade-assistant/cancel_reindex.asciidoc | 2 +- .../check_reindex_status.asciidoc | 8 ++-- .../api/upgrade-assistant/reindexing.asciidoc | 17 +++++-- docs/api/upgrade-assistant/status.asciidoc | 2 +- ...-plugin-core-public.doclinksstart.links.md | 5 ++- .../public/doc_links/doc_links_service.ts | 10 ++++- src/core/public/public.api.md | 5 ++- .../es_deprecations/es_deprecations.tsx | 44 +++++++++++++++++-- .../components/overview/overview.tsx | 2 +- 10 files changed, 79 insertions(+), 20 deletions(-) diff --git a/docs/api/upgrade-assistant/batch_reindexing.asciidoc b/docs/api/upgrade-assistant/batch_reindexing.asciidoc index db3e080d09185..6b355185de5ce 100644 --- a/docs/api/upgrade-assistant/batch_reindexing.asciidoc +++ b/docs/api/upgrade-assistant/batch_reindexing.asciidoc @@ -6,7 +6,7 @@ experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."] -Start or resume multiple reindexing tasks in one request. Additionally, reindexing tasks started or resumed +Start or resume multiple <> tasks in one request. Additionally, reindexing tasks started or resumed via the batch endpoint will be placed on a queue and executed one-by-one, which ensures that minimal cluster resources are consumed over time. @@ -76,7 +76,7 @@ Similar to the <>, the API retur } -------------------------------------------------- -<1> A list of reindex operations created, the order in the array indicates the order in which tasks will be executed. +<1> A list of reindex tasks created, the order in the array indicates the order in which tasks will be executed. <2> Presence of this key indicates that the reindex job will occur in the batch. <3> A Unix timestamp of when the reindex task was placed in the queue. <4> A list of errors that may have occurred preventing the reindex task from being created. diff --git a/docs/api/upgrade-assistant/cancel_reindex.asciidoc b/docs/api/upgrade-assistant/cancel_reindex.asciidoc index 04ab3bdde35fc..93e4c6fda6b40 100644 --- a/docs/api/upgrade-assistant/cancel_reindex.asciidoc +++ b/docs/api/upgrade-assistant/cancel_reindex.asciidoc @@ -4,7 +4,7 @@ Cancel reindex ++++ -experimental[] Cancel reindexes that are waiting for the {es} reindex task to complete. For example, `lastCompletedStep` set to `40`. +experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."] Cancel reindexes that are waiting for the Elasticsearch reindex task to complete. For example, `lastCompletedStep` set to `40`. diff --git a/docs/api/upgrade-assistant/check_reindex_status.asciidoc b/docs/api/upgrade-assistant/check_reindex_status.asciidoc index 75aac7b3699f5..934fd92312b04 100644 --- a/docs/api/upgrade-assistant/check_reindex_status.asciidoc +++ b/docs/api/upgrade-assistant/check_reindex_status.asciidoc @@ -4,7 +4,9 @@ Check reindex status ++++ -experimental[] Check the status of the reindex operation. +experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."] + +Check the status of the reindex task. [[check-reindex-status-request]] ==== Request @@ -43,7 +45,7 @@ The API returns the following: <2> Current status of the reindex. For details, see <>. <3> Last successfully completed step of the reindex. For details, see <> table. <4> Task ID of the reindex task in Elasticsearch. Only present if reindexing has started. -<5> Percentage of how far the reindexing task in Elasticsearch has progressed, in decimal from from 0 to 1. +<5> Percentage of how far the reindexing task in Elasticsearch has progressed, in decimal form from 0 to 1. <6> Error that caused the reindex to fail, if it failed. <7> An array of any warning codes explaining what changes are required for this reindex. For details, see <>. <8> Specifies if the user has sufficient privileges to reindex this index. When security is unavailable or disables, returns `true`. @@ -73,7 +75,7 @@ To resume the reindex, you must submit a new POST request to the `/api/upgrade_a ==== Step codes `0`:: - The reindex operation has been created in Kibana. + The reindex task has been created in Kibana. `10`:: The index group services stopped. Only applies to some system indices. diff --git a/docs/api/upgrade-assistant/reindexing.asciidoc b/docs/api/upgrade-assistant/reindexing.asciidoc index ce5670822e5ad..ccb9433ac24b1 100644 --- a/docs/api/upgrade-assistant/reindexing.asciidoc +++ b/docs/api/upgrade-assistant/reindexing.asciidoc @@ -4,9 +4,18 @@ Start or resume reindex ++++ -experimental[] Start a new reindex or resume a paused reindex. +experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."] + +Start a new reindex or resume a paused reindex. Following steps are performed during +a reindex task: + +. Setting the index to read-only +. Creating a new index +. {ref}/docs-reindex.html[Reindexing] documents into the new index +. Creating an index alias for the new index +. Deleting the old index + -Start a new reindex or resume a paused reindex. [[start-resume-reindex-request]] ==== Request @@ -40,6 +49,6 @@ The API returns the following: <1> The name of the new index. <2> The reindex status. For more information, refer to <>. <3> The last successfully completed step of the reindex. For more information, refer to <>. -<4> The task ID of the reindex task in {es}. Appears when the reindexing starts. -<5> The progress of the reindexing task in {es}. Appears in decimal form, from 0 to 1. +<4> The task ID of the {ref}/docs-reindex.html[reindex] task in {es}. Appears when the reindexing starts. +<5> The progress of the {ref}/docs-reindex.html[reindexing] task in {es}. Appears in decimal form, from 0 to 1. <6> The error that caused the reindex to fail, if it failed. diff --git a/docs/api/upgrade-assistant/status.asciidoc b/docs/api/upgrade-assistant/status.asciidoc index 42030061c4289..b0c11939ca784 100644 --- a/docs/api/upgrade-assistant/status.asciidoc +++ b/docs/api/upgrade-assistant/status.asciidoc @@ -4,7 +4,7 @@ Upgrade readiness status ++++ -experimental[] Check the status of your cluster. +experimental["The underlying Upgrade Assistant concepts are stable, but the APIs for managing Upgrade Assistant are experimental."] Check the status of your cluster. diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index ed6763db69ffe..3535681e73dde 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -133,7 +133,10 @@ readonly links: { }; readonly addData: string; readonly kibana: string; - readonly upgradeAssistant: string; + readonly upgradeAssistant: { + readonly overview: string; + readonly batchReindex: string; + }; readonly rollupJobs: string; readonly elasticsearch: Record; readonly siem: { diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index b6e640933ca08..a9f13c722e5ec 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -156,7 +156,10 @@ export class DocLinksService { }, addData: `${KIBANA_DOCS}connect-to-elasticsearch.html`, kibana: `${KIBANA_DOCS}index.html`, - upgradeAssistant: `${KIBANA_DOCS}upgrade-assistant.html`, + upgradeAssistant: { + overview: `${KIBANA_DOCS}upgrade-assistant.html`, + batchReindex: `${KIBANA_DOCS}batch-start-resume-reindex.html`, + }, rollupJobs: `${KIBANA_DOCS}data-rollups.html`, elasticsearch: { docsBase: `${ELASTICSEARCH_DOCS}`, @@ -644,7 +647,10 @@ export interface DocLinksStart { }; readonly addData: string; readonly kibana: string; - readonly upgradeAssistant: string; + readonly upgradeAssistant: { + readonly overview: string; + readonly batchReindex: string; + }; readonly rollupJobs: string; readonly elasticsearch: Record; readonly siem: { diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index cf0b526aa9fd9..8e9687747537e 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -600,7 +600,10 @@ export interface DocLinksStart { }; readonly addData: string; readonly kibana: string; - readonly upgradeAssistant: string; + readonly upgradeAssistant: { + readonly overview: string; + readonly batchReindex: string; + }; readonly rollupJobs: string; readonly elasticsearch: Record; readonly siem: { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 59416cc568668..012005e30571e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -8,8 +8,10 @@ import React, { useEffect, useMemo } from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { EuiPageHeader, EuiSpacer, EuiPageContent } from '@elastic/eui'; +import { EuiPageHeader, EuiSpacer, EuiPageContent, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { DocLinksStart } from 'kibana/public'; import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo } from '../../../../common/types'; @@ -44,16 +46,42 @@ const i18nTexts = { }), pageDescription: i18n.translate('xpack.upgradeAssistant.esDeprecations.pageDescription', { defaultMessage: - 'You must resolve all critical issues before upgrading. Back up recommended. Make sure you have a current snapshot before modifying your configuration or reindexing.', + 'Resolve all critical issues before upgrading. Before making changes, ensure you have a current snapshot of your cluster. Some issues may require reindexing to resolve. ', }), isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { defaultMessage: 'Loading deprecation issues…', }), }; +const getBatchReindexLink = (docLinks: DocLinksStart) => { + return ( + + {i18n.translate('xpack.upgradeAssistant.esDeprecations.batchReindexingDocsLink', { + defaultMessage: 'batch reindexing API', + })} + + ), + }} + /> + ); +}; + export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { const { - services: { api, breadcrumbs }, + services: { + api, + breadcrumbs, + core: { docLinks }, + }, } = useAppContext(); const { data: esDeprecations, isLoading, error, resendRequest } = api.useLoadEsDeprecations(); @@ -103,7 +131,15 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { return (

- + + {i18nTexts.pageDescription} + {getBatchReindexLink(docLinks)} + + } + > { })} rightSideItems={[ Date: Wed, 29 Sep 2021 13:52:57 +0100 Subject: [PATCH 45/93] [Upgrade Assistant] Improve error messages for GET /api/upgrade_assistant/reindex/ (#112961) --- .../es_deprecations.helpers.ts | 11 ++++ .../reindex_deprecation_flyout.test.ts | 47 ++++++++++++++ .../helpers/http_requests.ts | 24 ++++++++ .../plugins/upgrade_assistant/common/types.ts | 3 + .../checklist_step.test.tsx.snap | 1 + .../reindex/flyout/checklist_step.test.tsx | 28 ++++++++- .../reindex/flyout/checklist_step.tsx | 61 ++++++++++++++----- .../reindex/resolution_table_cell.tsx | 17 ++++++ .../reindex/use_reindex_state.tsx | 4 +- .../reindex_indices/reindex_indices.test.ts | 21 +++++++ .../routes/reindex_indices/reindex_indices.ts | 40 +++++++++--- 11 files changed, 229 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts index 96474f66dc629..9bb44a9314c52 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/es_deprecations.helpers.ts @@ -125,11 +125,22 @@ const createActions = (testBed: TestBed) => { }, }; + const reindexDeprecationFlyout = { + clickReindexButton: async () => { + await act(async () => { + find('startReindexingButton').simulate('click'); + }); + + component.update(); + }, + }; + return { table, searchBar, pagination, mlDeprecationFlyout, + reindexDeprecationFlyout, indexSettingsDeprecationFlyout, }; }; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts index d7ca0101d2b74..dce2fa6e18ac9 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts @@ -47,4 +47,51 @@ describe('Reindex deprecation flyout', () => { `Reindex ${reindexDeprecation.index}` ); }); + + it('renders error callout when reindex fails', async () => { + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: null, + warnings: [], + indexGroup: null, + hasRequiredPrivileges: true, + }); + + await act(async () => { + testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); + }); + + testBed.component.update(); + + const { actions, exists } = testBed; + + await actions.table.clickDeprecationRowAt('reindex', 0); + + httpRequestsMockHelpers.setStartReindexingResponse(undefined, { + statusCode: 404, + message: 'no such index [test]', + }); + + await actions.reindexDeprecationFlyout.clickReindexButton(); + + expect(exists('reindexDetails.reindexingFailedCallout')).toBe(true); + }); + + it('renders error callout when fetch status fails', async () => { + httpRequestsMockHelpers.setReindexStatusResponse(undefined, { + statusCode: 404, + message: 'no such index [test]', + }); + + await act(async () => { + testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); + }); + + testBed.component.update(); + + const { actions, exists } = testBed; + + await actions.table.clickDeprecationRowAt('reindex', 0); + + expect(exists('reindexDetails.fetchFailedCallout')).toBe(true); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts index e217ea4c5eff0..448eb79152894 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts @@ -115,6 +115,28 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setReindexStatusResponse = (response?: object, error?: ResponseError) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + + server.respondWith('GET', `${API_BASE_PATH}/reindex/:indexName`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + + const setStartReindexingResponse = (response?: object, error?: ResponseError) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + + server.respondWith('POST', `${API_BASE_PATH}/reindex/:indexName`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + const setDeleteMlSnapshotResponse = (response?: object, error?: ResponseError) => { const status = error ? error.statusCode || 400 : 200; const body = error ? error : response; @@ -147,6 +169,8 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { setDeleteMlSnapshotResponse, setUpgradeMlSnapshotStatusResponse, setLoadDeprecationLogsCountResponse, + setStartReindexingResponse, + setReindexStatusResponse, setLoadMlUpgradeModeResponse, }; }; diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 1614f8db6b853..3278d6a902c6d 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -28,6 +28,9 @@ export enum ReindexStatus { failed, paused, cancelled, + // Used by the UI to differentiate if there was a failure retrieving + // the status from the server API + fetchFailed, } export const REINDEX_OP_TYPE = 'upgrade-assistant-reindex-operation'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index ae03647042dbc..542cc51e45b9c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -80,6 +80,7 @@ exports[`ChecklistFlyout renders 1`] = ` > { expect((wrapper.find('EuiButton').props() as any).isLoading).toBe(true); }); - it('disables button if hasRequiredPrivileges is false', () => { + it('hides button if hasRequiredPrivileges is false', () => { const props = cloneDeep(defaultProps); props.reindexState.hasRequiredPrivileges = false; const wrapper = shallow(); - expect(wrapper.find('EuiButton').props().disabled).toBe(true); + expect(wrapper.exists('EuiButton')).toBe(false); + }); + + it('hides button if has error', () => { + const props = cloneDeep(defaultProps); + props.reindexState.status = ReindexStatus.fetchFailed; + props.reindexState.errorMessage = 'Index not found'; + const wrapper = shallow(); + expect(wrapper.exists('EuiButton')).toBe(false); + }); + + it('shows get status error callout', () => { + const props = cloneDeep(defaultProps); + props.reindexState.status = ReindexStatus.fetchFailed; + props.reindexState.errorMessage = 'Index not found'; + const wrapper = shallow(); + expect(wrapper.exists('[data-test-subj="fetchFailedCallout"]')).toBe(true); + }); + + it('shows reindexing callout', () => { + const props = cloneDeep(defaultProps); + props.reindexState.status = ReindexStatus.failed; + props.reindexState.errorMessage = 'Index not found'; + const wrapper = shallow(); + expect(wrapper.exists('[data-test-subj="reindexingFailedCallout"]')).toBe(true); }); it('calls startReindex when button is clicked', () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx index 1945de3613a3b..f40dfc8e86efa 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx @@ -76,6 +76,9 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ }> = ({ closeFlyout, reindexState, startReindex, cancelReindex, renderGlobalCallouts }) => { const { loadingState, status, hasRequiredPrivileges } = reindexState; const loading = loadingState === LoadingState.Loading || status === ReindexStatus.inProgress; + const isCompleted = status === ReindexStatus.completed; + const hasFetchFailed = status === ReindexStatus.fetchFailed; + const hasReindexingFailed = status === ReindexStatus.failed; const onStartReindex = useCallback(() => { uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_START_CLICK); @@ -90,6 +93,46 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ return ( + {hasRequiredPrivileges === false && ( + + + + } + color="danger" + iconType="alert" + /> + + )} + {(hasFetchFailed || hasReindexingFailed) && ( + <> + + + ) : ( + + ) + } + > + {reindexState.errorMessage} + + + )} {renderGlobalCallouts()}

- {!hasRequiredPrivileges && ( - - - - } - color="danger" - iconType="alert" - /> - - )}

@@ -152,7 +180,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ /> - {status !== ReindexStatus.completed && ( + {!hasFetchFailed && !isCompleted && hasRequiredPrivileges && ( {buttonLabel(status)} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx index 6ea9a0277059a..ff2f01befb180 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx @@ -45,6 +45,12 @@ const i18nTexts = { defaultMessage: 'Reindex failed', } ), + reindexFetchFailedText: i18n.translate( + 'xpack.upgradeAssistant.esDeprecations.reindex.reindexFetchFailedText', + { + defaultMessage: 'Reindex status not available', + } + ), reindexCanceledText: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.reindex.reindexCanceledText', { @@ -119,6 +125,17 @@ export const ReindexResolutionCell: React.FunctionComponent = () => { ); + case ReindexStatus.fetchFailed: + return ( + + + + + + {i18nTexts.reindexFetchFailedText} + + + ); case ReindexStatus.paused: return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index e1f01be2e0174..8890411cca2a0 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -100,7 +100,8 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A setReindexState({ ...reindexState, loadingState: LoadingState.Error, - status: ReindexStatus.failed, + errorMessage: error.message.toString(), + status: ReindexStatus.fetchFailed, }); return; } @@ -137,6 +138,7 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A setReindexState({ ...reindexState, loadingState: LoadingState.Error, + errorMessage: error.message.toString(), status: ReindexStatus.failed, }); return; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts index 44331799a160b..403df67c3e93f 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts @@ -11,6 +11,8 @@ import { licensingMock } from '../../../../licensing/server/mocks'; import { securityMock } from '../../../../security/server/mocks'; import { createMockRouter, MockRouter, routeHandlerContextMock } from '../__mocks__/routes.mock'; import { createRequestMock } from '../__mocks__/request.mock'; +import { handleEsError } from '../../shared_imports'; +import { errors as esErrors } from '@elastic/elasticsearch'; const mockReindexService = { hasRequiredPrivileges: jest.fn(), @@ -60,6 +62,7 @@ describe('reindex API', () => { credentialStore, router: mockRouter, licensing: licensingMock.createSetup(), + lib: { handleEsError }, getSecurityPlugin: () => securityMock.createStart(), }; registerReindexIndicesRoutes(routeDependencies, () => worker); @@ -125,6 +128,24 @@ describe('reindex API', () => { ]); }); + it('returns es errors', async () => { + mockReindexService.findReindexOperation.mockResolvedValueOnce(null); + mockReindexService.detectReindexWarnings.mockRejectedValueOnce( + new esErrors.ResponseError({ statusCode: 404 } as any) + ); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/reindex/{indexName}', + })( + routeHandlerContextMock, + createRequestMock({ params: { indexName: 'anIndex' } }), + kibanaResponseFactory + ); + + expect(resp.status).toEqual(404); + }); + it("returns null for both if reindex operation doesn't exist and index doesn't exist", async () => { mockReindexService.findReindexOperation.mockResolvedValueOnce(null); mockReindexService.detectReindexWarnings.mockResolvedValueOnce(null); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts index 6edc03d86cb85..57ea99308e70f 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts @@ -6,6 +6,7 @@ */ import { schema } from '@kbn/config-schema'; +import { ResponseError } from '@elastic/elasticsearch/lib/errors'; import { API_BASE_PATH } from '../../../common/constants'; import { ElasticsearchServiceStart, @@ -82,11 +83,19 @@ const mapAnyErrorToKibanaHttpResponse = (e: any) => { // nothing matched } } + throw e; }; export function registerReindexIndicesRoutes( - { credentialStore, router, licensing, log, getSecurityPlugin }: RouteDependencies, + { + credentialStore, + router, + licensing, + log, + getSecurityPlugin, + lib: { handleEsError }, + }: RouteDependencies, getWorker: () => ReindexWorker ) { const BASE_PATH = `${API_BASE_PATH}/reindex`; @@ -131,8 +140,11 @@ export function registerReindexIndicesRoutes( return response.ok({ body: result, }); - } catch (e) { - return mapAnyErrorToKibanaHttpResponse(e); + } catch (error) { + if (error instanceof ResponseError) { + return handleEsError({ error, response }); + } + return mapAnyErrorToKibanaHttpResponse(error); } } ) @@ -166,8 +178,11 @@ export function registerReindexIndicesRoutes( return response.ok({ body: result, }); - } catch (e) { - return mapAnyErrorToKibanaHttpResponse(e); + } catch (error) { + if (error instanceof ResponseError) { + return handleEsError({ error, response }); + } + return mapAnyErrorToKibanaHttpResponse(error); } } ); @@ -276,8 +291,11 @@ export function registerReindexIndicesRoutes( hasRequiredPrivileges, }, }); - } catch (e) { - return mapAnyErrorToKibanaHttpResponse(e); + } catch (error) { + if (error instanceof ResponseError) { + return handleEsError({ error, response }); + } + return mapAnyErrorToKibanaHttpResponse(error); } } ) @@ -319,8 +337,12 @@ export function registerReindexIndicesRoutes( await reindexService.cancelReindexing(indexName); return response.ok({ body: { acknowledged: true } }); - } catch (e) { - return mapAnyErrorToKibanaHttpResponse(e); + } catch (error) { + if (error instanceof ResponseError) { + return handleEsError({ error, response }); + } + + return mapAnyErrorToKibanaHttpResponse(error); } } ) From 86991fe180f23993e0d7dd745cfeadb988ee43ee Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Wed, 29 Sep 2021 07:01:28 -0700 Subject: [PATCH 46/93] Add support for single manual steps to Upgrade Assistant. (#113344) --- .../kibana_deprecations_service.mock.ts | 4 ++- .../deprecation_details_flyout.test.ts | 25 +++++++++--------- .../deprecation_details_flyout.tsx | 26 +++++++++++++------ 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts index fb3c48785c5f0..c51e415d7e916 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts @@ -10,7 +10,8 @@ import type { DeprecationsServiceStart, DomainDeprecationDetails } from 'kibana/ const kibanaDeprecations: DomainDeprecationDetails[] = [ { correctiveActions: { - manualSteps: ['Step 1', 'Step 2', 'Step 3'], + // Only has one manual step. + manualSteps: ['Step 1'], api: { method: 'POST', path: '/test', @@ -24,6 +25,7 @@ const kibanaDeprecations: DomainDeprecationDetails[] = [ }, { correctiveActions: { + // Has multiple manual steps. manualSteps: ['Step 1', 'Step 2', 'Step 3'], }, domainId: 'test_domain_2', diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts index 11b7dc72ea5d2..1b782ae36181c 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts @@ -40,22 +40,26 @@ describe('Kibana deprecation details flyout', () => { }); describe('Deprecation with manual steps', () => { - test('renders flyout with manual steps only', async () => { + test('renders flyout with single manual step as a standalone paragraph', async () => { const { find, exists, actions } = testBed; const manualDeprecation = mockedKibanaDeprecations[1]; - await actions.table.clickDeprecationAt(1); + await actions.table.clickDeprecationAt(0); expect(exists('kibanaDeprecationDetails')).toBe(true); - expect(exists('kibanaDeprecationDetails.warningDeprecationBadge')).toBe(true); expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe(manualDeprecation.title); - expect(find('manualStepsList').find('li').length).toEqual( - manualDeprecation.correctiveActions.manualSteps.length - ); + expect(find('manualStep').length).toBe(1); + }); - // Quick resolve callout and button should not display - expect(exists('quickResolveCallout')).toBe(false); - expect(exists('resolveButton')).toBe(false); + test('renders flyout with multiple manual steps as a list', async () => { + const { find, exists, actions } = testBed; + const manualDeprecation = mockedKibanaDeprecations[1]; + + await actions.table.clickDeprecationAt(1); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe(manualDeprecation.title); + expect(find('manualStepsListItem').length).toBe(3); }); }); @@ -71,9 +75,6 @@ describe('Kibana deprecation details flyout', () => { expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe( quickResolveDeprecation.title ); - expect(find('manualStepsList').find('li').length).toEqual( - quickResolveDeprecation.correctiveActions.manualSteps.length - ); // Quick resolve callout and button should display expect(exists('quickResolveCallout')).toBe(true); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index 6ec9ad175e112..37b07bc159577 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -203,16 +203,26 @@ export const DeprecationDetailsFlyout = ({

{i18nTexts.manualFixTitle}

- + -
    - {correctiveActions.manualSteps.map((step, stepIndex) => ( -
  1. - {step} -
  2. - ))} -
+ {correctiveActions.manualSteps.length === 1 ? ( +

+ {correctiveActions.manualSteps[0]} +

+ ) : ( +
    + {correctiveActions.manualSteps.map((step, stepIndex) => ( +
  1. + {step} +
  2. + ))} +
+ )}

)} From 733874b96645e8536d349a45ec3d0665df6811b1 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 1 Oct 2021 15:17:16 -0700 Subject: [PATCH 47/93] Revert "[Upgrade Assistant] Refactor telemetry (#112177)" (#113665) This reverts commit 991d24bad21ccf4b8350cba2b2ed3ceca6d90cea. --- .../schema/xpack_plugins.json | 38 ++++ x-pack/plugins/upgrade_assistant/README.md | 27 +-- .../plugins/upgrade_assistant/common/types.ts | 29 +++ .../index_settings/flyout.tsx | 16 +- .../deprecation_types/ml_snapshots/flyout.tsx | 8 - .../checklist_step.test.tsx.snap | 4 +- .../reindex/flyout/checklist_step.tsx | 22 +-- .../deprecation_types/reindex/table_row.tsx | 21 +- .../reindex/use_reindex_state.tsx | 4 + .../es_deprecations/es_deprecations.tsx | 22 ++- .../deprecation_details_flyout.tsx | 11 +- .../kibana_deprecations.tsx | 13 +- .../overview/backup_step/cloud_backup.tsx | 8 +- .../overview/backup_step/on_prem_backup.tsx | 11 +- .../deprecations_count_checkpoint.tsx | 5 +- .../overview/fix_logs_step/external_links.tsx | 27 +-- .../components/overview/overview.tsx | 13 +- .../public/application/lib/api.ts | 20 ++ .../public/application/lib/ui_metric.ts | 49 ----- .../upgrade_assistant/public/plugin.ts | 10 +- .../plugins/upgrade_assistant/public/types.ts | 2 - .../lib/telemetry/es_ui_open_apis.test.ts | 48 +++++ .../server/lib/telemetry/es_ui_open_apis.ts | 57 ++++++ .../lib/telemetry/es_ui_reindex_apis.test.ts | 52 +++++ .../lib/telemetry/es_ui_reindex_apis.ts | 63 ++++++ .../lib/telemetry/usage_collector.test.ts | 31 +++ .../server/lib/telemetry/usage_collector.ts | 113 ++++++++++- .../upgrade_assistant/server/plugin.ts | 3 +- .../server/routes/register_routes.ts | 2 + .../server/routes/telemetry.test.ts | 187 ++++++++++++++++++ .../server/routes/telemetry.ts | 64 ++++++ .../telemetry_saved_object_type.ts | 36 ++++ 32 files changed, 809 insertions(+), 207 deletions(-) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index ab1b77587bf78..b3ca5f17634d5 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -7329,6 +7329,44 @@ } } } + }, + "ui_open": { + "properties": { + "elasticsearch": { + "type": "long", + "_meta": { + "description": "Number of times a user viewed the list of Elasticsearch deprecations." + } + }, + "overview": { + "type": "long", + "_meta": { + "description": "Number of times a user viewed the Overview page." + } + }, + "kibana": { + "type": "long", + "_meta": { + "description": "Number of times a user viewed the list of Kibana deprecations" + } + } + } + }, + "ui_reindex": { + "properties": { + "close": { + "type": "long" + }, + "open": { + "type": "long" + }, + "start": { + "type": "long" + }, + "stop": { + "type": "long" + } + } } } }, diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index 6570e7f8d7617..255eb94a0318c 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -226,29 +226,4 @@ This is a non-exhaustive list of different error scenarios in Upgrade Assistant. - **Error updating deprecation logging status.** Mock a `404` status code to `PUT /api/upgrade_assistant/deprecation_logging`. Alternatively, edit [this line](https://github.com/elastic/kibana/blob/545c1420c285af8f5eee56f414bd6eca735aea11/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts#L77) locally and replace `deprecation_logging` with `fake_deprecation_logging`. - **Unauthorized error fetching ES deprecations.** Mock a `403` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 403 }` - **Partially upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": false } }` -- **Upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": true } }` - -### Telemetry - -The Upgrade Assistant tracks several triggered events in the UI, using Kibana Usage Collection service's [UI counters](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#ui-counters). - -**Overview page** -- Component loaded -- Click event for "Create snapshot" button -- Click event for "View deprecation logs in Observability" link -- Click event for "Analyze logs in Discover" link -- Click event for "Reset counter" button - -**ES deprecations page** -- Component loaded -- Click events for starting and stopping reindex tasks -- Click events for upgrading or deleting a Machine Learning snapshot -- Click event for deleting a deprecated index setting - -**Kibana deprecations page** -- Component loaded -- Click event for "Quick resolve" button - -In addition to UI counters, the Upgrade Assistant has a [custom usage collector](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#custom-collector). It currently is only responsible for tracking whether the user has deprecation logging enabled or not. - -For testing instructions, refer to the [Kibana Usage Collection service README](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#testing). \ No newline at end of file +- **Upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": true } }` \ No newline at end of file diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 3278d6a902c6d..a7a2cab67751b 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -138,7 +138,32 @@ export interface UIReindex { stop: boolean; } +export interface UpgradeAssistantTelemetrySavedObject { + ui_open: { + overview: number; + elasticsearch: number; + kibana: number; + }; + ui_reindex: { + close: number; + open: number; + start: number; + stop: number; + }; +} + export interface UpgradeAssistantTelemetry { + ui_open: { + overview: number; + elasticsearch: number; + kibana: number; + }; + ui_reindex: { + close: number; + open: number; + start: number; + stop: number; + }; features: { deprecation_logging: { enabled: boolean; @@ -146,6 +171,10 @@ export interface UpgradeAssistantTelemetry { }; } +export interface UpgradeAssistantTelemetrySavedObjectAttributes { + [key: string]: any; +} + export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; export interface DeprecationInfo { level: MIGRATION_DEPRECATION_LEVEL; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx index e00edb4f3b11d..24c1897fbdd02 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx @@ -5,9 +5,8 @@ * 2.0. */ -import React, { useCallback } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButton, EuiButtonEmpty, @@ -26,7 +25,6 @@ import { } from '@elastic/eui'; import { EnrichedDeprecationInfo, IndexSettingAction } from '../../../../../../common/types'; import type { ResponseError } from '../../../../lib/api'; -import { uiMetricService, UIM_INDEX_SETTINGS_DELETE_CLICK } from '../../../../lib/ui_metric'; import type { Status } from '../../../types'; import { DeprecationBadge } from '../../../shared'; @@ -109,11 +107,6 @@ export const RemoveIndexSettingsFlyout = ({ // Flag used to hide certain parts of the UI if the deprecation has been resolved or is in progress const isResolvable = ['idle', 'error'].includes(statusType); - const onRemoveSettings = useCallback(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_INDEX_SETTINGS_DELETE_CLICK); - removeIndexSettings(index!, (correctiveAction as IndexSettingAction).deprecatedSettings); - }, [correctiveAction, index, removeIndexSettings]); - return ( <> @@ -197,7 +190,12 @@ export const RemoveIndexSettingsFlyout = ({ fill data-test-subj="deleteSettingsButton" color="danger" - onClick={onRemoveSettings} + onClick={() => + removeIndexSettings( + index!, + (correctiveAction as IndexSettingAction).deprecatedSettings + ) + } > {statusType === 'error' ? i18nTexts.retryRemoveButtonLabel diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index 2a36f3e33e83c..4e3d77ba72ae8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButton, @@ -26,11 +25,6 @@ import { } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; -import { - uiMetricService, - UIM_ML_SNAPSHOT_UPGRADE_CLICK, - UIM_ML_SNAPSHOT_DELETE_CLICK, -} from '../../../../lib/ui_metric'; import { DeprecationBadge } from '../../../shared'; import { MlSnapshotContext } from './context'; import { useAppContext } from '../../../../app_context'; @@ -179,13 +173,11 @@ export const FixSnapshotsFlyout = ({ const isResolved = snapshotState.status === 'complete'; const onUpgradeSnapshot = () => { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_ML_SNAPSHOT_UPGRADE_CLICK); upgradeSnapshot(); closeFlyout(); }; const onDeleteSnapshot = () => { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_ML_SNAPSHOT_DELETE_CLICK); deleteSnapshot(); closeFlyout(); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index 542cc51e45b9c..26119c2b62040 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -42,7 +42,7 @@ exports[`ChecklistFlyout renders 1`] = ` { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_START_CLICK); - startReindex(); - }, [startReindex]); - - const onStopReindex = useCallback(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_STOP_CLICK); - cancelReindex(); - }, [cancelReindex]); - return ( @@ -168,7 +152,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ /> - + @@ -186,7 +170,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ fill color={status === ReindexStatus.paused ? 'warning' : 'primary'} iconType={status === ReindexStatus.paused ? 'play' : undefined} - onClick={onStartReindex} + onClick={startReindex} isLoading={loading} disabled={loading || !hasRequiredPrivileges} data-test-subj="startReindexingButton" diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx index 1059720e66a59..c2a14ca5be858 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx @@ -7,15 +7,9 @@ import React, { useState, useEffect, useCallback } from 'react'; import { EuiTableRowCell } from '@elastic/eui'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GlobalFlyout } from '../../../../../shared_imports'; import { useAppContext } from '../../../../app_context'; -import { - uiMetricService, - UIM_REINDEX_CLOSE_FLYOUT_CLICK, - UIM_REINDEX_OPEN_FLYOUT_CLICK, -} from '../../../../lib/ui_metric'; import { DeprecationTableColumns } from '../../../types'; import { EsDeprecationsTableCells } from '../../es_deprecations_table_cells'; import { ReindexResolutionCell } from './resolution_table_cell'; @@ -35,6 +29,9 @@ const ReindexTableRowCells: React.FunctionComponent = ({ }) => { const [showFlyout, setShowFlyout] = useState(false); const reindexState = useReindexContext(); + const { + services: { api }, + } = useAppContext(); const { addContent: addContentToGlobalFlyout, removeContent: removeContentFromGlobalFlyout } = useGlobalFlyout(); @@ -42,8 +39,8 @@ const ReindexTableRowCells: React.FunctionComponent = ({ const closeFlyout = useCallback(async () => { removeContentFromGlobalFlyout('reindexFlyout'); setShowFlyout(false); - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_CLOSE_FLYOUT_CLICK); - }, [removeContentFromGlobalFlyout]); + await api.sendReindexTelemetryData({ close: true }); + }, [api, removeContentFromGlobalFlyout]); useEffect(() => { if (showFlyout) { @@ -67,9 +64,13 @@ const ReindexTableRowCells: React.FunctionComponent = ({ useEffect(() => { if (showFlyout) { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_OPEN_FLYOUT_CLICK); + async function sendTelemetry() { + await api.sendReindexTelemetryData({ open: true }); + } + + sendTelemetry(); } - }, [showFlyout]); + }, [showFlyout, api]); return ( <> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index 8890411cca2a0..87891c5d8d219 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -132,6 +132,8 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A cancelLoadingState: undefined, }); + api.sendReindexTelemetryData({ start: true }); + const { data, error } = await api.startReindexTask(indexName); if (error) { @@ -149,6 +151,8 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A }, [api, indexName, reindexState, updateStatus]); const cancelReindex = useCallback(async () => { + api.sendReindexTelemetryData({ stop: true }); + const { error } = await api.cancelReindexTask(indexName); setReindexState({ diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 012005e30571e..09f7eaf298f55 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -12,12 +12,10 @@ import { EuiPageHeader, EuiSpacer, EuiPageContent, EuiLink } from '@elastic/eui' import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { DocLinksStart } from 'kibana/public'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo } from '../../../../common/types'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; -import { uiMetricService, UIM_ES_DEPRECATIONS_PAGE_LOAD } from '../../lib/ui_metric'; import { getEsDeprecationError } from '../../lib/get_es_deprecation_error'; import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { EsDeprecationsTable } from './es_deprecations_table'; @@ -84,7 +82,13 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { }, } = useAppContext(); - const { data: esDeprecations, isLoading, error, resendRequest } = api.useLoadEsDeprecations(); + const { + data: esDeprecations, + isLoading, + error, + resendRequest, + isInitialRequest, + } = api.useLoadEsDeprecations(); const deprecationsCountByLevel: { warningDeprecations: number; @@ -98,8 +102,16 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { }, [breadcrumbs]); useEffect(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_ES_DEPRECATIONS_PAGE_LOAD); - }, []); + if (isLoading === false && isInitialRequest) { + async function sendTelemetryData() { + await api.sendPageTelemetryData({ + elasticsearch: true, + }); + } + + sendTelemetryData(); + } + }, [api, isLoading, isInitialRequest]); if (error) { return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index 37b07bc159577..a1242c2da9b0c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -5,10 +5,9 @@ * 2.0. */ -import React, { useCallback } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButtonEmpty, @@ -25,7 +24,6 @@ import { EuiSpacer, } from '@elastic/eui'; -import { uiMetricService, UIM_KIBANA_QUICK_RESOLVE_CLICK } from '../../lib/ui_metric'; import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; import { DeprecationBadge } from '../shared'; @@ -136,11 +134,6 @@ export const DeprecationDetailsFlyout = ({ const isCurrent = deprecationResolutionState?.id === deprecation.id; const isResolved = isCurrent && deprecationResolutionState?.resolveDeprecationStatus === 'ok'; - const onResolveDeprecation = useCallback(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_KIBANA_QUICK_RESOLVE_CLICK); - resolveDeprecation(deprecation); - }, [deprecation, resolveDeprecation]); - return ( <> @@ -242,7 +235,7 @@ export const DeprecationDetailsFlyout = ({ resolveDeprecation(deprecation)} isLoading={Boolean( deprecationResolutionState?.resolveDeprecationStatus === 'in_progress' )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 35147b2f4cf39..8158f8462da1e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -11,12 +11,10 @@ import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { METRIC_TYPE } from '@kbn/analytics'; import type { DomainDeprecationDetails } from 'kibana/public'; import { SectionLoading, GlobalFlyout } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; -import { uiMetricService, UIM_KIBANA_DEPRECATIONS_PAGE_LOAD } from '../../lib/ui_metric'; import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { KibanaDeprecationsTable } from './kibana_deprecations_table'; import { @@ -118,6 +116,7 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) services: { core: { deprecations }, breadcrumbs, + api, }, } = useAppContext(); @@ -228,8 +227,14 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) ]); useEffect(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_KIBANA_DEPRECATIONS_PAGE_LOAD); - }, []); + async function sendTelemetryData() { + await api.sendPageTelemetryData({ + kibana: true, + }); + } + + sendTelemetryData(); + }, [api]); useEffect(() => { breadcrumbs.setBreadcrumbs('kibanaDeprecations'); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx index 5d329e1b0bd26..abef34a27f30f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx @@ -9,7 +9,6 @@ import React, { useEffect } from 'react'; import moment from 'moment-timezone'; import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiLoadingContent, EuiFlexGroup, @@ -22,7 +21,6 @@ import { } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; -import { uiMetricService, UIM_BACKUP_DATA_CLOUD_CLICK } from '../../../lib/ui_metric'; interface Props { cloudSnapshotsUrl: string; @@ -135,13 +133,11 @@ export const CloudBackup: React.FunctionComponent = ({ return ( <> {statusMessage} + - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} + { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_BACKUP_DATA_CLOUD_CLICK); - }} data-test-subj="cloudSnapshotsLink" target="_blank" iconType="popout" diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx index 69100b36db7eb..2e2e2bd5ce48e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx @@ -8,11 +8,9 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; -import { uiMetricService, UIM_BACKUP_DATA_ON_PREM_CLICK } from '../../../lib/ui_metric'; const SnapshotRestoreAppLink: React.FunctionComponent = () => { const { @@ -24,14 +22,7 @@ const SnapshotRestoreAppLink: React.FunctionComponent = () => { ?.useUrl({ page: 'snapshots' }); return ( - // eslint-disable-next-line @elastic/eui/href-or-on-click - { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_BACKUP_DATA_ON_PREM_CLICK); - }} - data-test-subj="snapshotRestoreLink" - > + ( @@ -74,7 +72,6 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ const onResetClick = () => { const now = moment().toISOString(); - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_RESET_LOGS_COUNTER_CLICK); setCheckpoint(now); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx index 69f1f14d4eb58..d027b2f262e9e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx @@ -9,17 +9,10 @@ import { encode } from 'rison-node'; import React, { FunctionComponent, useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { METRIC_TYPE } from '@kbn/analytics'; import { EuiLink, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiPanel, EuiText } from '@elastic/eui'; -import { DataPublicPluginStart } from '../../../../shared_imports'; import { useAppContext } from '../../../app_context'; -import { - uiMetricService, - UIM_OBSERVABILITY_CLICK, - UIM_DISCOVER_CLICK, -} from '../../../lib/ui_metric'; - +import { DataPublicPluginStart } from '../../../../shared_imports'; import { DEPRECATION_LOGS_INDEX_PATTERN, DEPRECATION_LOGS_SOURCE_ID, @@ -80,14 +73,7 @@ const DiscoverAppLink: FunctionComponent = ({ checkpoint }) => { }, [dataService, checkpoint, share.url.locators]); return ( - // eslint-disable-next-line @elastic/eui/href-or-on-click - { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_DISCOVER_CLICK); - }} - data-test-subj="viewDiscoverLogs" - > + = ({ checkpoint }) => { ); return ( - // eslint-disable-next-line @elastic/eui/href-or-on-click - { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_OBSERVABILITY_CLICK); - }} - data-test-subj="viewObserveLogs" - > + { kibanaVersionInfo: { nextMajor }, services: { breadcrumbs, + api, core: { docLinks }, }, plugins: { cloud }, } = useAppContext(); useEffect(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_OVERVIEW_PAGE_LOAD); - }, []); + async function sendTelemetryData() { + await api.sendPageTelemetryData({ + overview: true, + }); + } + + sendTelemetryData(); + }, [api]); useEffect(() => { breadcrumbs.setBreadcrumbs('overview'); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index 1d51510333ef4..da4f87f497467 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -65,6 +65,16 @@ export class ApiService { }); } + public async sendPageTelemetryData(telemetryData: { [tabName: string]: boolean }) { + const result = await this.sendRequest({ + path: `${API_BASE_PATH}/stats/ui_open`, + method: 'put', + body: JSON.stringify(telemetryData), + }); + + return result; + } + public useLoadDeprecationLogging() { return this.useRequest<{ isDeprecationLogIndexingEnabled: boolean; @@ -140,6 +150,16 @@ export class ApiService { }); } + public async sendReindexTelemetryData(telemetryData: { [key: string]: boolean }) { + const result = await this.sendRequest({ + path: `${API_BASE_PATH}/stats/ui_reindex`, + method: 'put', + body: JSON.stringify(telemetryData), + }); + + return result; + } + public async getReindexStatus(indexName: string) { return await this.sendRequest({ path: `${API_BASE_PATH}/reindex/${indexName}`, diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts deleted file mode 100644 index 394f046a8bafe..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { UiCounterMetricType } from '@kbn/analytics'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; - -export const UIM_APP_NAME = 'upgrade_assistant'; -export const UIM_ES_DEPRECATIONS_PAGE_LOAD = 'es_deprecations_page_load'; -export const UIM_KIBANA_DEPRECATIONS_PAGE_LOAD = 'kibana_deprecations_page_load'; -export const UIM_OVERVIEW_PAGE_LOAD = 'overview_page_load'; -export const UIM_REINDEX_OPEN_FLYOUT_CLICK = 'reindex_open_flyout_click'; -export const UIM_REINDEX_CLOSE_FLYOUT_CLICK = 'reindex_close_flyout_click'; -export const UIM_REINDEX_START_CLICK = 'reindex_start_click'; -export const UIM_REINDEX_STOP_CLICK = 'reindex_stop_click'; -export const UIM_BACKUP_DATA_CLOUD_CLICK = 'backup_data_cloud_click'; -export const UIM_BACKUP_DATA_ON_PREM_CLICK = 'backup_data_on_prem_click'; -export const UIM_RESET_LOGS_COUNTER_CLICK = 'reset_logs_counter_click'; -export const UIM_OBSERVABILITY_CLICK = 'observability_click'; -export const UIM_DISCOVER_CLICK = 'discover_click'; -export const UIM_ML_SNAPSHOT_UPGRADE_CLICK = 'ml_snapshot_upgrade_click'; -export const UIM_ML_SNAPSHOT_DELETE_CLICK = 'ml_snapshot_delete_click'; -export const UIM_INDEX_SETTINGS_DELETE_CLICK = 'index_settings_delete_click'; -export const UIM_KIBANA_QUICK_RESOLVE_CLICK = 'kibana_quick_resolve_click'; - -export class UiMetricService { - private usageCollection: UsageCollectionSetup | undefined; - - public setup(usageCollection: UsageCollectionSetup) { - this.usageCollection = usageCollection; - } - - private track(metricType: UiCounterMetricType, eventName: string | string[]) { - if (!this.usageCollection) { - // Usage collection might be disabled in Kibana config. - return; - } - return this.usageCollection.reportUiCounter(UIM_APP_NAME, metricType, eventName); - } - - public trackUiMetric(metricType: UiCounterMetricType, eventName: string | string[]) { - return this.track(metricType, eventName); - } -} - -export const uiMetricService = new UiMetricService(); diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index aed21c058740f..bafcae79acc13 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -11,7 +11,6 @@ import { Plugin, CoreSetup, PluginInitializerContext } from 'src/core/public'; import { apiService } from './application/lib/api'; import { breadcrumbService } from './application/lib/breadcrumbs'; -import { uiMetricService } from './application/lib/ui_metric'; import { SetupDependencies, StartDependencies, AppDependencies, ClientConfigType } from './types'; export class UpgradeAssistantUIPlugin @@ -19,10 +18,7 @@ export class UpgradeAssistantUIPlugin { constructor(private ctx: PluginInitializerContext) {} - setup( - coreSetup: CoreSetup, - { management, cloud, share, usageCollection }: SetupDependencies - ) { + setup(coreSetup: CoreSetup, { management, cloud, share }: SetupDependencies) { const { readonly, ui: { enabled: isUpgradeAssistantUiEnabled }, @@ -42,10 +38,6 @@ export class UpgradeAssistantUIPlugin defaultMessage: 'Upgrade Assistant', }); - if (usageCollection) { - uiMetricService.setup(usageCollection); - } - appRegistrar.registerApp({ id: 'upgrade_assistant', title: pluginName, diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index ace009d9c74aa..4d47c10fdeec2 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -10,7 +10,6 @@ import { ManagementSetup } from 'src/plugins/management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SharePluginSetup } from 'src/plugins/share/public'; import { CoreStart } from 'src/core/public'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; import { BreadcrumbService } from './application/lib/breadcrumbs'; @@ -26,7 +25,6 @@ export interface SetupDependencies { management: ManagementSetup; share: SharePluginSetup; cloud?: CloudSetup; - usageCollection?: UsageCollectionSetup; } export interface StartDependencies { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts new file mode 100644 index 0000000000000..caff78390b9d1 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; + +import { upsertUIOpenOption } from './es_ui_open_apis'; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the lib/telemetry tests. + */ +describe('Upgrade Assistant Telemetry SavedObject UIOpen', () => { + describe('Upsert UIOpen Option', () => { + it('call saved objects internal repository with the correct info', async () => { + const internalRepo = savedObjectsRepositoryMock.create(); + + await upsertUIOpenOption({ + overview: true, + elasticsearch: true, + kibana: true, + savedObjects: { createInternalRepository: () => internalRepo } as any, + }); + + expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(3); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + ['ui_open.overview'] + ); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + ['ui_open.elasticsearch'] + ); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + ['ui_open.kibana'] + ); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts new file mode 100644 index 0000000000000..3d463fe4b03ed --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsServiceStart } from 'src/core/server'; +import { + UIOpen, + UIOpenOption, + UPGRADE_ASSISTANT_DOC_ID, + UPGRADE_ASSISTANT_TYPE, +} from '../../../common/types'; + +interface IncrementUIOpenDependencies { + uiOpenOptionCounter: UIOpenOption; + savedObjects: SavedObjectsServiceStart; +} + +async function incrementUIOpenOptionCounter({ + savedObjects, + uiOpenOptionCounter, +}: IncrementUIOpenDependencies) { + const internalRepository = savedObjects.createInternalRepository(); + + await internalRepository.incrementCounter(UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, [ + `ui_open.${uiOpenOptionCounter}`, + ]); +} + +type UpsertUIOpenOptionDependencies = UIOpen & { savedObjects: SavedObjectsServiceStart }; + +export async function upsertUIOpenOption({ + overview, + elasticsearch, + savedObjects, + kibana, +}: UpsertUIOpenOptionDependencies): Promise { + if (overview) { + await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'overview' }); + } + + if (elasticsearch) { + await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'elasticsearch' }); + } + + if (kibana) { + await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'kibana' }); + } + + return { + overview, + elasticsearch, + kibana, + }; +} diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts new file mode 100644 index 0000000000000..6a05e8a697bb8 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; +import { upsertUIReindexOption } from './es_ui_reindex_apis'; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the lib/telemetry tests. + */ +describe('Upgrade Assistant Telemetry SavedObject UIReindex', () => { + describe('Upsert UIReindex Option', () => { + it('call saved objects internal repository with the correct info', async () => { + const internalRepo = savedObjectsRepositoryMock.create(); + await upsertUIReindexOption({ + close: true, + open: true, + start: true, + stop: true, + savedObjects: { createInternalRepository: () => internalRepo } as any, + }); + + expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(4); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + [`ui_reindex.close`] + ); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + [`ui_reindex.open`] + ); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + [`ui_reindex.start`] + ); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + [`ui_reindex.stop`] + ); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts new file mode 100644 index 0000000000000..caee1a58a4006 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsServiceStart } from 'src/core/server'; +import { + UIReindex, + UIReindexOption, + UPGRADE_ASSISTANT_DOC_ID, + UPGRADE_ASSISTANT_TYPE, +} from '../../../common/types'; + +interface IncrementUIReindexOptionDependencies { + uiReindexOptionCounter: UIReindexOption; + savedObjects: SavedObjectsServiceStart; +} + +async function incrementUIReindexOptionCounter({ + savedObjects, + uiReindexOptionCounter, +}: IncrementUIReindexOptionDependencies) { + const internalRepository = savedObjects.createInternalRepository(); + + await internalRepository.incrementCounter(UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, [ + `ui_reindex.${uiReindexOptionCounter}`, + ]); +} + +type UpsertUIReindexOptionDepencies = UIReindex & { savedObjects: SavedObjectsServiceStart }; + +export async function upsertUIReindexOption({ + start, + close, + open, + stop, + savedObjects, +}: UpsertUIReindexOptionDepencies): Promise { + if (close) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'close' }); + } + + if (open) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'open' }); + } + + if (start) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'start' }); + } + + if (stop) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'stop' }); + } + + return { + close, + open, + start, + stop, + }; +} diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts index 34d329557f11e..50c5b358aa5cb 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts @@ -47,6 +47,26 @@ describe('Upgrade Assistant Usage Collector', () => { }; dependencies = { usageCollection, + savedObjects: { + createInternalRepository: jest.fn().mockImplementation(() => { + return { + get: () => { + return { + attributes: { + 'ui_open.overview': 10, + 'ui_open.elasticsearch': 20, + 'ui_open.kibana': 15, + 'ui_reindex.close': 1, + 'ui_reindex.open': 4, + 'ui_reindex.start': 2, + 'ui_reindex.stop': 1, + 'ui_reindex.not_defined': 1, + }, + }; + }, + }; + }), + }, elasticsearch: { client: clusterClient, }, @@ -71,6 +91,17 @@ describe('Upgrade Assistant Usage Collector', () => { callClusterStub ); expect(upgradeAssistantStats).toEqual({ + ui_open: { + overview: 10, + elasticsearch: 20, + kibana: 15, + }, + ui_reindex: { + close: 1, + open: 4, + start: 2, + stop: 1, + }, features: { deprecation_logging: { enabled: true, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index c535cd14f104d..56932f5e54b06 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -5,14 +5,43 @@ * 2.0. */ -import { ElasticsearchClient, ElasticsearchServiceStart } from 'src/core/server'; +import { get } from 'lodash'; +import { + ElasticsearchClient, + ElasticsearchServiceStart, + ISavedObjectsRepository, + SavedObjectsServiceStart, +} from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { UpgradeAssistantTelemetry } from '../../../common/types'; +import { + UPGRADE_ASSISTANT_DOC_ID, + UPGRADE_ASSISTANT_TYPE, + UpgradeAssistantTelemetry, + UpgradeAssistantTelemetrySavedObject, + UpgradeAssistantTelemetrySavedObjectAttributes, +} from '../../../common/types'; import { isDeprecationLogIndexingEnabled, isDeprecationLoggingEnabled, } from '../es_deprecation_logging_apis'; +async function getSavedObjectAttributesFromRepo( + savedObjectsRepository: ISavedObjectsRepository, + docType: string, + docID: string +) { + try { + return ( + await savedObjectsRepository.get( + docType, + docID + ) + ).attributes; + } catch (e) { + return null; + } +} + async function getDeprecationLoggingStatusValue(esClient: ElasticsearchClient): Promise { try { const { body: loggerDeprecationCallResult } = await esClient.cluster.getSettings({ @@ -28,14 +57,58 @@ async function getDeprecationLoggingStatusValue(esClient: ElasticsearchClient): } } -export async function fetchUpgradeAssistantMetrics({ - client: esClient, -}: ElasticsearchServiceStart): Promise { +export async function fetchUpgradeAssistantMetrics( + { client: esClient }: ElasticsearchServiceStart, + savedObjects: SavedObjectsServiceStart +): Promise { + const savedObjectsRepository = savedObjects.createInternalRepository(); + const upgradeAssistantSOAttributes = await getSavedObjectAttributesFromRepo( + savedObjectsRepository, + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID + ); const deprecationLoggingStatusValue = await getDeprecationLoggingStatusValue( esClient.asInternalUser ); + const getTelemetrySavedObject = ( + upgradeAssistantTelemetrySavedObjectAttrs: UpgradeAssistantTelemetrySavedObjectAttributes | null + ): UpgradeAssistantTelemetrySavedObject => { + const defaultTelemetrySavedObject = { + ui_open: { + overview: 0, + elasticsearch: 0, + kibana: 0, + }, + ui_reindex: { + close: 0, + open: 0, + start: 0, + stop: 0, + }, + }; + + if (!upgradeAssistantTelemetrySavedObjectAttrs) { + return defaultTelemetrySavedObject; + } + + return { + ui_open: { + overview: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.overview', 0), + elasticsearch: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.elasticsearch', 0), + kibana: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.kibana', 0), + }, + ui_reindex: { + close: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.close', 0), + open: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.open', 0), + start: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.start', 0), + stop: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.stop', 0), + }, + } as UpgradeAssistantTelemetrySavedObject; + }; + return { + ...getTelemetrySavedObject(upgradeAssistantSOAttributes), features: { deprecation_logging: { enabled: deprecationLoggingStatusValue, @@ -46,12 +119,14 @@ export async function fetchUpgradeAssistantMetrics({ interface Dependencies { elasticsearch: ElasticsearchServiceStart; + savedObjects: SavedObjectsServiceStart; usageCollection: UsageCollectionSetup; } export function registerUpgradeAssistantUsageCollector({ elasticsearch, usageCollection, + savedObjects, }: Dependencies) { const upgradeAssistantUsageCollector = usageCollection.makeUsageCollector({ @@ -68,8 +143,34 @@ export function registerUpgradeAssistantUsageCollector({ }, }, }, + ui_open: { + elasticsearch: { + type: 'long', + _meta: { + description: 'Number of times a user viewed the list of Elasticsearch deprecations.', + }, + }, + overview: { + type: 'long', + _meta: { + description: 'Number of times a user viewed the Overview page.', + }, + }, + kibana: { + type: 'long', + _meta: { + description: 'Number of times a user viewed the list of Kibana deprecations', + }, + }, + }, + ui_reindex: { + close: { type: 'long' }, + open: { type: 'long' }, + start: { type: 'long' }, + stop: { type: 'long' }, + }, }, - fetch: async () => fetchUpgradeAssistantMetrics(elasticsearch), + fetch: async () => fetchUpgradeAssistantMetrics(elasticsearch, savedObjects), }); usageCollection.registerCollector(upgradeAssistantUsageCollector); diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index 717f03758f825..2062cf982d15f 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -142,10 +142,11 @@ export class UpgradeAssistantServerPlugin implements Plugin { registerRoutes(dependencies, this.getWorker.bind(this)); if (usageCollection) { - getStartServices().then(([{ elasticsearch }]) => { + getStartServices().then(([{ savedObjects: savedObjectsService, elasticsearch }]) => { registerUpgradeAssistantUsageCollector({ elasticsearch, usageCollection, + savedObjects: savedObjectsService, }); }); } diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index 002f34a489cff..8b63233a124a7 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -12,6 +12,7 @@ import { registerCloudBackupStatusRoutes } from './cloud_backup_status'; import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; import { registerReindexIndicesRoutes } from './reindex_indices'; +import { registerTelemetryRoutes } from './telemetry'; import { registerUpdateSettingsRoute } from './update_index_settings'; import { registerMlSnapshotRoutes } from './ml_snapshots'; import { ReindexWorker } from '../lib/reindexing'; @@ -23,6 +24,7 @@ export function registerRoutes(dependencies: RouteDependencies, getWorker: () => registerESDeprecationRoutes(dependencies); registerDeprecationLoggingRoutes(dependencies); registerReindexIndicesRoutes(dependencies, getWorker); + registerTelemetryRoutes(dependencies); registerUpdateSettingsRoute(dependencies); registerMlSnapshotRoutes(dependencies); // Route for cloud to retrieve the upgrade status for ES and Kibana diff --git a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts new file mode 100644 index 0000000000000..578cceb702751 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts @@ -0,0 +1,187 @@ +/* + * 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 { kibanaResponseFactory } from 'src/core/server'; +import { savedObjectsServiceMock } from 'src/core/server/mocks'; +import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; + +jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ + upsertUIOpenOption: jest.fn(), +})); + +jest.mock('../lib/telemetry/es_ui_reindex_apis', () => ({ + upsertUIReindexOption: jest.fn(), +})); + +import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; +import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; +import { registerTelemetryRoutes } from './telemetry'; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the lib/telemetry tests. + */ +describe('Upgrade Assistant Telemetry API', () => { + let routeDependencies: any; + let mockRouter: MockRouter; + beforeEach(() => { + mockRouter = createMockRouter(); + routeDependencies = { + getSavedObjectsService: () => savedObjectsServiceMock.create(), + router: mockRouter, + }; + registerTelemetryRoutes(routeDependencies); + }); + afterEach(() => jest.clearAllMocks()); + + describe('PUT /api/upgrade_assistant/stats/ui_open', () => { + it('returns correct payload with single option', async () => { + const returnPayload = { + overview: true, + elasticsearch: false, + kibana: false, + }; + + (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await routeDependencies.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/stats/ui_open', + })( + routeHandlerContextMock, + createRequestMock({ body: returnPayload }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns correct payload with multiple option', async () => { + const returnPayload = { + overview: true, + elasticsearch: true, + kibana: true, + }; + + (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await routeDependencies.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/stats/ui_open', + })( + routeHandlerContextMock, + createRequestMock({ + body: { + overview: true, + elasticsearch: true, + kibana: true, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns an error if it throws', async () => { + (upsertUIOpenOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + + await expect( + routeDependencies.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/stats/ui_open', + })( + routeHandlerContextMock, + createRequestMock({ + body: { + overview: false, + }, + }), + kibanaResponseFactory + ) + ).rejects.toThrowError('scary error!'); + }); + }); + + describe('PUT /api/upgrade_assistant/stats/ui_reindex', () => { + it('returns correct payload with single option', async () => { + const returnPayload = { + close: false, + open: false, + start: true, + stop: false, + }; + + (upsertUIReindexOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await routeDependencies.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/stats/ui_reindex', + })( + routeHandlerContextMock, + createRequestMock({ + body: { + overview: false, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns correct payload with multiple option', async () => { + const returnPayload = { + close: true, + open: true, + start: true, + stop: true, + }; + + (upsertUIReindexOption as jest.Mock).mockResolvedValue(returnPayload); + + const resp = await routeDependencies.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/stats/ui_reindex', + })( + routeHandlerContextMock, + createRequestMock({ + body: { + close: true, + open: true, + start: true, + stop: true, + }, + }), + kibanaResponseFactory + ); + + expect(resp.payload).toEqual(returnPayload); + }); + + it('returns an error if it throws', async () => { + (upsertUIReindexOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + + await expect( + routeDependencies.router.getHandler({ + method: 'put', + pathPattern: '/api/upgrade_assistant/stats/ui_reindex', + })( + routeHandlerContextMock, + createRequestMock({ + body: { + start: false, + }, + }), + kibanaResponseFactory + ) + ).rejects.toThrowError('scary error!'); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts new file mode 100644 index 0000000000000..d083b38c7c240 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { API_BASE_PATH } from '../../common/constants'; +import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; +import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; +import { RouteDependencies } from '../types'; + +export function registerTelemetryRoutes({ router, getSavedObjectsService }: RouteDependencies) { + router.put( + { + path: `${API_BASE_PATH}/stats/ui_open`, + validate: { + body: schema.object({ + overview: schema.boolean({ defaultValue: false }), + elasticsearch: schema.boolean({ defaultValue: false }), + kibana: schema.boolean({ defaultValue: false }), + }), + }, + }, + async (ctx, request, response) => { + const { elasticsearch, overview, kibana } = request.body; + return response.ok({ + body: await upsertUIOpenOption({ + savedObjects: getSavedObjectsService(), + elasticsearch, + overview, + kibana, + }), + }); + } + ); + + router.put( + { + path: `${API_BASE_PATH}/stats/ui_reindex`, + validate: { + body: schema.object({ + close: schema.boolean({ defaultValue: false }), + open: schema.boolean({ defaultValue: false }), + start: schema.boolean({ defaultValue: false }), + stop: schema.boolean({ defaultValue: false }), + }), + }, + }, + async (ctx, request, response) => { + const { close, open, start, stop } = request.body; + return response.ok({ + body: await upsertUIReindexOption({ + savedObjects: getSavedObjectsService(), + close, + open, + start, + stop, + }), + }); + } + ); +} diff --git a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts index cb3fbcaef59b7..42d5d339dd050 100644 --- a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts +++ b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts @@ -15,6 +15,42 @@ export const telemetrySavedObjectType: SavedObjectsType = { namespaceType: 'agnostic', mappings: { properties: { + ui_open: { + properties: { + overview: { + type: 'long', + null_value: 0, + }, + elasticsearch: { + type: 'long', + null_value: 0, + }, + kibana: { + type: 'long', + null_value: 0, + }, + }, + }, + ui_reindex: { + properties: { + close: { + type: 'long', + null_value: 0, + }, + open: { + type: 'long', + null_value: 0, + }, + start: { + type: 'long', + null_value: 0, + }, + stop: { + type: 'long', + null_value: 0, + }, + }, + }, features: { properties: { deprecation_logging: { From d11fd4a49be45138eef159f36d92308a02275f28 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 5 Oct 2021 06:48:13 +0100 Subject: [PATCH 48/93] [Upgrade Assistant] Use skipFetchFields when creating the indexPattern in order to avoid errors if index doesn't exist (#113821) * Use skipFetchFields when creating the indexPatter in order to avoid errors when index doesnt exist * Address CR feedback Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fix_logs_step/external_links.test.ts | 49 +++++++++++++++++++ .../overview/fix_logs_step/external_links.tsx | 14 +++++- 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.test.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.test.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.test.ts new file mode 100644 index 0000000000000..64a8920324d89 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.test.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getDeprecationIndexPatternId } from './external_links'; + +import { DEPRECATION_LOGS_INDEX_PATTERN } from '../../../../../common/constants'; +import { dataPluginMock, Start } from '../../../../../../../../src/plugins/data/public/mocks'; + +describe('External Links', () => { + let dataService: Start; + + beforeEach(() => { + dataService = dataPluginMock.createStartContract(); + }); + + describe('getDeprecationIndexPatternId', () => { + it('creates new index pattern if doesnt exist', async () => { + dataService.dataViews.find = jest.fn().mockResolvedValue([]); + dataService.dataViews.createAndSave = jest.fn().mockResolvedValue({ id: '123-456' }); + + const indexPatternId = await getDeprecationIndexPatternId(dataService); + + expect(indexPatternId).toBe('123-456'); + // prettier-ignore + expect(dataService.dataViews.createAndSave).toHaveBeenCalledWith({ + title: DEPRECATION_LOGS_INDEX_PATTERN, + allowNoIndex: true, + }, false, true); + }); + + it('uses existing index pattern if it already exists', async () => { + dataService.dataViews.find = jest.fn().mockResolvedValue([ + { + id: '123-456', + title: DEPRECATION_LOGS_INDEX_PATTERN, + }, + ]); + + const indexPatternId = await getDeprecationIndexPatternId(dataService); + + expect(indexPatternId).toBe('123-456'); + expect(dataService.dataViews.find).toHaveBeenCalledWith(DEPRECATION_LOGS_INDEX_PATTERN); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx index d027b2f262e9e..7d26e4db69713 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx @@ -22,7 +22,7 @@ interface Props { checkpoint: string; } -const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) => { +export const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) => { const results = await dataService.dataViews.find(DEPRECATION_LOGS_INDEX_PATTERN); // Since the find might return also results with wildcard matchers we need to find the // index pattern that has an exact match with our title. @@ -33,10 +33,20 @@ const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) if (deprecationIndexPattern) { return deprecationIndexPattern.id; } else { + // When creating the index pattern, we need to be careful when creating an indexPattern + // for an index that doesnt exist. Since the deprecation logs data stream is only created + // when a deprecation log is indexed it could be possible that it might not exist at the + // time we need to render the DiscoveryAppLink. + // So in order to avoid those errors we need to make sure that the indexPattern is created + // with allowNoIndex and that we skip fetching fields to from the source index. + const override = false; + const skipFetchFields = true; + // prettier-ignore const newIndexPattern = await dataService.dataViews.createAndSave({ title: DEPRECATION_LOGS_INDEX_PATTERN, allowNoIndex: true, - }); + }, override, skipFetchFields); + return newIndexPattern.id; } }; From e78511d3561c62f5e76eba77a4ea81793ee94c0e Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 5 Oct 2021 09:10:44 +0100 Subject: [PATCH 49/93] [Upgrade Assistant] Hide system indices from es deprecations list (#113627) --- .../plugins/upgrade_assistant/common/types.ts | 16 ++++++ .../lib/__fixtures__/fake_deprecations.json | 9 ++++ .../server/lib/es_deprecations_status.test.ts | 45 ++++++++++++++++ .../server/lib/es_deprecations_status.ts | 15 +++++- .../lib/es_system_indices_upgrade.test.ts | 52 +++++++++++++++++++ .../server/lib/es_system_indices_upgrade.ts | 36 +++++++++++++ 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.ts diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index a7a2cab67751b..3a539dba32b49 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -257,3 +257,19 @@ export interface DeprecationLoggingStatus { isDeprecationLogIndexingEnabled: boolean; isDeprecationLoggingEnabled: boolean; } + +export type UPGRADE_STATUS = 'UPGRADE_NEEDED' | 'NO_UPGRADE_NEEDED' | 'IN_PROGRESS'; +export interface SystemIndicesUpgradeFeature { + id?: string; + feature_name: string; + minimum_index_version: string; + upgrade_status: UPGRADE_STATUS; + indices: Array<{ + index: string; + version: string; + }>; +} +export interface SystemIndicesUpgradeStatus { + features: SystemIndicesUpgradeFeature[]; + upgrade_status: UPGRADE_STATUS; +} diff --git a/x-pack/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json b/x-pack/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json index 617bb02ff9dfc..2337e0e2dc039 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json +++ b/x-pack/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json @@ -102,6 +102,15 @@ "resolve_during_rolling_upgrade": false } ], + ".ml-config": [ + { + "level": "critical", + "message": "Index created before 7.0", + "url": "https://www.elastic.co/guide/en/elasticsearch/reference/6.0/breaking_60_mappings_changes.html#_coercion_of_boolean_fields", + "details": "This index was created using version: 6.8.16", + "resolve_during_rolling_upgrade": false + } + ], ".watcher-history-6-2018.11.07": [ { "level": "warning", diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts index 99c101e04e36b..d27a02ae97fdd 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts @@ -40,6 +40,25 @@ describe('getESUpgradeStatus', () => { asApiResponse(deprecationsResponse) ); + esClient.asCurrentUser.transport.request.mockResolvedValue( + asApiResponse({ + features: [ + { + feature_name: 'machine_learning', + minimum_index_version: '7.1.1', + upgrade_status: 'UPGRADE_NEEDED', + indices: [ + { + index: '.ml-config', + version: '7.1.1', + }, + ], + }, + ], + upgrade_status: 'UPGRADE_NEEDED', + }) + ); + // @ts-expect-error not full interface of response esClient.asCurrentUser.indices.resolveIndex.mockResolvedValue(asApiResponse(resolvedIndices)); @@ -86,4 +105,30 @@ describe('getESUpgradeStatus', () => { 0 ); }); + + it('filters out system indices returned by upgrade system indices API', async () => { + esClient.asCurrentUser.migration.deprecations.mockResolvedValue( + asApiResponse({ + cluster_settings: [], + node_settings: [], + ml_settings: [], + index_settings: { + '.ml-config': [ + { + level: 'critical', + message: 'Index created before 7.0', + url: 'https://', + details: '...', + resolve_during_rolling_upgrade: false, + }, + ], + }, + }) + ); + + const upgradeStatus = await getESUpgradeStatus(esClient); + + expect(upgradeStatus.deprecations).toHaveLength(0); + expect(upgradeStatus.totalCriticalDeprecations).toBe(0); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts index aa08ecef78d32..401967d678a35 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts @@ -11,6 +11,10 @@ import { indexSettingDeprecations } from '../../common/constants'; import { EnrichedDeprecationInfo, ESUpgradeStatus } from '../../common/types'; import { esIndicesStateCheck } from './es_indices_state_check'; +import { + getESSystemIndicesUpgradeStatus, + convertFeaturesToIndicesArray, +} from '../lib/es_system_indices_upgrade'; export async function getESUpgradeStatus( dataClient: IScopedClusterClient @@ -19,10 +23,19 @@ export async function getESUpgradeStatus( const getCombinedDeprecations = async () => { const indices = await getCombinedIndexInfos(deprecations, dataClient); + const systemIndices = await getESSystemIndicesUpgradeStatus(dataClient.asCurrentUser); + const systemIndicesList = convertFeaturesToIndicesArray(systemIndices.features); return Object.keys(deprecations).reduce((combinedDeprecations, deprecationType) => { if (deprecationType === 'index_settings') { - combinedDeprecations = combinedDeprecations.concat(indices); + // We need to exclude all index related deprecations for system indices since + // they are resolved separately through the system indices upgrade section in + // the Overview page. + const withoutSystemIndices = indices.filter( + (index) => !systemIndicesList.includes(index.index!) + ); + + combinedDeprecations = combinedDeprecations.concat(withoutSystemIndices); } else { const deprecationsByType = deprecations[ deprecationType as keyof estypes.MigrationDeprecationsResponse diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.test.ts new file mode 100644 index 0000000000000..a4a6e1053702c --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { convertFeaturesToIndicesArray } from './es_system_indices_upgrade'; +import { SystemIndicesUpgradeStatus } from '../../common/types'; + +const esUpgradeSystemIndicesStatusMock: SystemIndicesUpgradeStatus = { + features: [ + { + feature_name: 'machine_learning', + minimum_index_version: '7.1.1', + upgrade_status: 'UPGRADE_NEEDED', + indices: [ + { + index: '.ml-config', + version: '7.1.1', + }, + { + index: '.ml-notifications', + version: '7.1.1', + }, + ], + }, + { + feature_name: 'security', + minimum_index_version: '7.1.1', + upgrade_status: 'UPGRADE_NEEDED', + indices: [ + { + index: '.ml-config', + version: '7.1.1', + }, + ], + }, + ], + upgrade_status: 'UPGRADE_NEEDED', +}; + +describe('convertFeaturesToIndicesArray', () => { + it('converts list with features to flat array of uniq indices', async () => { + const result = convertFeaturesToIndicesArray(esUpgradeSystemIndicesStatusMock.features); + expect(result).toEqual(['.ml-config', '.ml-notifications']); + }); + + it('returns empty array if no features are passed to it', async () => { + expect(convertFeaturesToIndicesArray([])).toEqual([]); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.ts new file mode 100644 index 0000000000000..32cea54a884e3 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.ts @@ -0,0 +1,36 @@ +/* + * 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 { flow, flatMap, map, flatten, uniq } from 'lodash/fp'; +import { ElasticsearchClient } from 'src/core/server'; +import { SystemIndicesUpgradeStatus, SystemIndicesUpgradeFeature } from '../../common/types'; + +export const convertFeaturesToIndicesArray = ( + features: SystemIndicesUpgradeFeature[] +): string[] => { + return flow( + // Map each feature into Indices[] + map('indices'), + // Flatten each into an string[] of indices + map(flatMap('index')), + // Flatten the array + flatten, + // And finally dedupe the indices + uniq + )(features); +}; + +export const getESSystemIndicesUpgradeStatus = async ( + client: ElasticsearchClient +): Promise => { + const { body } = await client.transport.request({ + method: 'GET', + path: '/_migration/system_features', + }); + + return body as SystemIndicesUpgradeStatus; +}; From 456f6770c0de9430439de04455541293f1f0cd4e Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 5 Oct 2021 07:24:17 -0700 Subject: [PATCH 50/93] Refactor reindex routes into separate single and batch reindex files. Apply version precheck to batch routes. (#113822) --- .../server/routes/register_routes.ts | 3 +- .../batch_reindex_indices.test.ts | 192 ++++++++++++++++++ .../reindex_indices/batch_reindex_indices.ts | 133 ++++++++++++ .../reindex_indices/create_reindex_worker.ts | 38 ++++ .../server/routes/reindex_indices/index.ts | 4 +- .../map_any_error_to_kibana_http_response.ts | 45 ++++ .../reindex_indices/reindex_indices.test.ts | 105 ---------- .../routes/reindex_indices/reindex_indices.ts | 172 +--------------- 8 files changed, 415 insertions(+), 277 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/create_reindex_worker.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/map_any_error_to_kibana_http_response.ts diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index 8b63233a124a7..cc4be54042583 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -11,7 +11,7 @@ import { registerAppRoutes } from './app'; import { registerCloudBackupStatusRoutes } from './cloud_backup_status'; import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; -import { registerReindexIndicesRoutes } from './reindex_indices'; +import { registerReindexIndicesRoutes, registerBatchReindexIndicesRoutes } from './reindex_indices'; import { registerTelemetryRoutes } from './telemetry'; import { registerUpdateSettingsRoute } from './update_index_settings'; import { registerMlSnapshotRoutes } from './ml_snapshots'; @@ -24,6 +24,7 @@ export function registerRoutes(dependencies: RouteDependencies, getWorker: () => registerESDeprecationRoutes(dependencies); registerDeprecationLoggingRoutes(dependencies); registerReindexIndicesRoutes(dependencies, getWorker); + registerBatchReindexIndicesRoutes(dependencies, getWorker); registerTelemetryRoutes(dependencies); registerUpdateSettingsRoute(dependencies); registerMlSnapshotRoutes(dependencies); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.test.ts new file mode 100644 index 0000000000000..961b63b30f4ea --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.test.ts @@ -0,0 +1,192 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kibanaResponseFactory } from 'src/core/server'; +import { loggingSystemMock } from 'src/core/server/mocks'; +import { licensingMock } from '../../../../licensing/server/mocks'; +import { securityMock } from '../../../../security/server/mocks'; +import { createMockRouter, MockRouter, routeHandlerContextMock } from '../__mocks__/routes.mock'; +import { createRequestMock } from '../__mocks__/request.mock'; +import { handleEsError } from '../../shared_imports'; + +const mockReindexService = { + hasRequiredPrivileges: jest.fn(), + detectReindexWarnings: jest.fn(), + getIndexGroup: jest.fn(), + createReindexOperation: jest.fn(), + findAllInProgressOperations: jest.fn(), + findReindexOperation: jest.fn(), + processNextStep: jest.fn(), + resumeReindexOperation: jest.fn(), + cancelReindexing: jest.fn(), +}; +jest.mock('../../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); + +jest.mock('../../lib/reindexing', () => { + return { + reindexServiceFactory: () => mockReindexService, + }; +}); + +import { credentialStoreFactory } from '../../lib/reindexing/credential_store'; +import { registerBatchReindexIndicesRoutes } from './batch_reindex_indices'; + +const logMock = loggingSystemMock.create().get(); + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. Business logic is tested + * more thoroughly in the es_migration_apis test. + */ +describe('reindex API', () => { + let routeDependencies: any; + let mockRouter: MockRouter; + + const credentialStore = credentialStoreFactory(logMock); + const worker = { + includes: jest.fn(), + forceRefresh: jest.fn(), + } as any; + + beforeEach(() => { + mockRouter = createMockRouter(); + routeDependencies = { + credentialStore, + router: mockRouter, + licensing: licensingMock.createSetup(), + lib: { handleEsError }, + getSecurityPlugin: () => securityMock.createStart(), + }; + registerBatchReindexIndicesRoutes(routeDependencies, () => worker); + + mockReindexService.hasRequiredPrivileges.mockResolvedValue(true); + mockReindexService.detectReindexWarnings.mockReset(); + mockReindexService.getIndexGroup.mockReset(); + mockReindexService.createReindexOperation.mockReset(); + mockReindexService.findAllInProgressOperations.mockReset(); + mockReindexService.findReindexOperation.mockReset(); + mockReindexService.processNextStep.mockReset(); + mockReindexService.resumeReindexOperation.mockReset(); + mockReindexService.cancelReindexing.mockReset(); + worker.includes.mockReset(); + worker.forceRefresh.mockReset(); + + // Reset the credentialMap + credentialStore.clear(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('POST /api/upgrade_assistant/reindex/batch', () => { + const queueSettingsArg = { + enqueue: true, + }; + it('creates a collection of index operations', async () => { + mockReindexService.createReindexOperation + .mockResolvedValueOnce({ + attributes: { indexName: 'theIndex1' }, + }) + .mockResolvedValueOnce({ + attributes: { indexName: 'theIndex2' }, + }) + .mockResolvedValueOnce({ + attributes: { indexName: 'theIndex3' }, + }); + + const resp = await routeDependencies.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/batch', + })( + routeHandlerContextMock, + createRequestMock({ body: { indexNames: ['theIndex1', 'theIndex2', 'theIndex3'] } }), + kibanaResponseFactory + ); + + // It called create correctly + expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( + 1, + 'theIndex1', + queueSettingsArg + ); + expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( + 2, + 'theIndex2', + queueSettingsArg + ); + expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( + 3, + 'theIndex3', + queueSettingsArg + ); + + // It returned the right results + expect(resp.status).toEqual(200); + const data = resp.payload; + expect(data).toEqual({ + errors: [], + enqueued: [ + { indexName: 'theIndex1' }, + { indexName: 'theIndex2' }, + { indexName: 'theIndex3' }, + ], + }); + }); + + it('gracefully handles partial successes', async () => { + mockReindexService.createReindexOperation + .mockResolvedValueOnce({ + attributes: { indexName: 'theIndex1' }, + }) + .mockRejectedValueOnce(new Error('oops!')); + + mockReindexService.hasRequiredPrivileges + .mockResolvedValueOnce(true) + .mockResolvedValueOnce(false) + .mockResolvedValueOnce(true); + + const resp = await routeDependencies.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/reindex/batch', + })( + routeHandlerContextMock, + createRequestMock({ body: { indexNames: ['theIndex1', 'theIndex2', 'theIndex3'] } }), + kibanaResponseFactory + ); + + // It called create correctly + expect(mockReindexService.createReindexOperation).toHaveBeenCalledTimes(2); + expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( + 1, + 'theIndex1', + queueSettingsArg + ); + expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( + 2, + 'theIndex3', + queueSettingsArg + ); + + // It returned the right results + expect(resp.status).toEqual(200); + const data = resp.payload; + expect(data).toEqual({ + errors: [ + { + indexName: 'theIndex2', + message: 'You do not have adequate privileges to reindex "theIndex2".', + }, + { indexName: 'theIndex3', message: 'oops!' }, + ], + enqueued: [{ indexName: 'theIndex1' }], + }); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts new file mode 100644 index 0000000000000..732eedd6c3605 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { ResponseError } from '@elastic/elasticsearch/lib/errors'; + +import { API_BASE_PATH } from '../../../common/constants'; +import { ReindexStatus } from '../../../common/types'; +import { versionCheckHandlerWrapper } from '../../lib/es_version_precheck'; +import { ReindexWorker } from '../../lib/reindexing'; +import { reindexActionsFactory } from '../../lib/reindexing/reindex_actions'; +import { sortAndOrderReindexOperations } from '../../lib/reindexing/op_utils'; +import { RouteDependencies } from '../../types'; +import { mapAnyErrorToKibanaHttpResponse } from './map_any_error_to_kibana_http_response'; +import { reindexHandler } from './reindex_handler'; +import { GetBatchQueueResponse, PostBatchResponse } from './types'; + +export function registerBatchReindexIndicesRoutes( + { + credentialStore, + router, + licensing, + log, + getSecurityPlugin, + lib: { handleEsError }, + }: RouteDependencies, + getWorker: () => ReindexWorker +) { + const BASE_PATH = `${API_BASE_PATH}/reindex`; + + // Get the current batch queue + router.get( + { + path: `${BASE_PATH}/batch/queue`, + validate: {}, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { client: esClient }, + savedObjects, + }, + }, + request, + response + ) => { + const { client } = savedObjects; + const callAsCurrentUser = esClient.asCurrentUser; + const reindexActions = reindexActionsFactory(client, callAsCurrentUser); + try { + const inProgressOps = await reindexActions.findAllByStatus(ReindexStatus.inProgress); + const { queue } = sortAndOrderReindexOperations(inProgressOps); + const result: GetBatchQueueResponse = { + queue: queue.map((savedObject) => savedObject.attributes), + }; + return response.ok({ + body: result, + }); + } catch (error) { + if (error instanceof ResponseError) { + return handleEsError({ error, response }); + } + return mapAnyErrorToKibanaHttpResponse(error); + } + } + ) + ); + + // Add indices for reindexing to the worker's batch + router.post( + { + path: `${BASE_PATH}/batch`, + validate: { + body: schema.object({ + indexNames: schema.arrayOf(schema.string()), + }), + }, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + savedObjects: { client: savedObjectsClient }, + elasticsearch: { client: esClient }, + }, + }, + request, + response + ) => { + const { indexNames } = request.body; + const results: PostBatchResponse = { + enqueued: [], + errors: [], + }; + for (const indexName of indexNames) { + try { + const result = await reindexHandler({ + savedObjects: savedObjectsClient, + dataClient: esClient, + indexName, + log, + licensing, + request, + credentialStore, + reindexOptions: { + enqueue: true, + }, + security: getSecurityPlugin(), + }); + results.enqueued.push(result); + } catch (e) { + results.errors.push({ + indexName, + message: e.message, + }); + } + } + + if (results.errors.length < indexNames.length) { + // Kick the worker on this node to immediately pickup the batch. + getWorker().forceRefresh(); + } + + return response.ok({ body: results }); + } + ) + ); +} diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/create_reindex_worker.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/create_reindex_worker.ts new file mode 100644 index 0000000000000..72d68fc132cb6 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/create_reindex_worker.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + ElasticsearchServiceStart, + Logger, + SavedObjectsClient, +} from '../../../../../../src/core/server'; + +import { LicensingPluginSetup } from '../../../../licensing/server'; +import { SecurityPluginStart } from '../../../../security/server'; +import { ReindexWorker } from '../../lib/reindexing'; +import { CredentialStore } from '../../lib/reindexing/credential_store'; + +interface CreateReindexWorker { + logger: Logger; + elasticsearchService: ElasticsearchServiceStart; + credentialStore: CredentialStore; + savedObjects: SavedObjectsClient; + licensing: LicensingPluginSetup; + security: SecurityPluginStart; +} + +export function createReindexWorker({ + logger, + elasticsearchService, + credentialStore, + savedObjects, + licensing, + security, +}: CreateReindexWorker) { + const esClient = elasticsearchService.client; + return new ReindexWorker(savedObjects, credentialStore, esClient, logger, licensing, security); +} diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/index.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/index.ts index 97d8f495c16bb..038f0c07c11fe 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/index.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/index.ts @@ -5,4 +5,6 @@ * 2.0. */ -export { createReindexWorker, registerReindexIndicesRoutes } from './reindex_indices'; +export { createReindexWorker } from './create_reindex_worker'; +export { registerReindexIndicesRoutes } from './reindex_indices'; +export { registerBatchReindexIndicesRoutes } from './batch_reindex_indices'; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/map_any_error_to_kibana_http_response.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/map_any_error_to_kibana_http_response.ts new file mode 100644 index 0000000000000..f36e52ffb0eab --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/map_any_error_to_kibana_http_response.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kibanaResponseFactory } from '../../../../../../src/core/server'; + +import { + AccessForbidden, + CannotCreateIndex, + IndexNotFound, + MultipleReindexJobsFound, + ReindexAlreadyInProgress, + ReindexCannotBeCancelled, + ReindexTaskCannotBeDeleted, + ReindexTaskFailed, +} from '../../lib/reindexing/error_symbols'; +import { ReindexError } from '../../lib/reindexing/error'; + +export const mapAnyErrorToKibanaHttpResponse = (e: any) => { + if (e instanceof ReindexError) { + switch (e.symbol) { + case AccessForbidden: + return kibanaResponseFactory.forbidden({ body: e.message }); + case IndexNotFound: + return kibanaResponseFactory.notFound({ body: e.message }); + case CannotCreateIndex: + case ReindexTaskCannotBeDeleted: + throw e; + case ReindexTaskFailed: + // Bad data + return kibanaResponseFactory.customError({ body: e.message, statusCode: 422 }); + case ReindexAlreadyInProgress: + case MultipleReindexJobsFound: + case ReindexCannotBeCancelled: + return kibanaResponseFactory.badRequest({ body: e.message }); + default: + // nothing matched + } + } + + throw e; +}; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts index 403df67c3e93f..c510790800f64 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts @@ -295,111 +295,6 @@ describe('reindex API', () => { }); }); - describe('POST /api/upgrade_assistant/reindex/batch', () => { - const queueSettingsArg = { - enqueue: true, - }; - it('creates a collection of index operations', async () => { - mockReindexService.createReindexOperation - .mockResolvedValueOnce({ - attributes: { indexName: 'theIndex1' }, - }) - .mockResolvedValueOnce({ - attributes: { indexName: 'theIndex2' }, - }) - .mockResolvedValueOnce({ - attributes: { indexName: 'theIndex3' }, - }); - - const resp = await routeDependencies.router.getHandler({ - method: 'post', - pathPattern: '/api/upgrade_assistant/reindex/batch', - })( - routeHandlerContextMock, - createRequestMock({ body: { indexNames: ['theIndex1', 'theIndex2', 'theIndex3'] } }), - kibanaResponseFactory - ); - - // It called create correctly - expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( - 1, - 'theIndex1', - queueSettingsArg - ); - expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( - 2, - 'theIndex2', - queueSettingsArg - ); - expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( - 3, - 'theIndex3', - queueSettingsArg - ); - - // It returned the right results - expect(resp.status).toEqual(200); - const data = resp.payload; - expect(data).toEqual({ - errors: [], - enqueued: [ - { indexName: 'theIndex1' }, - { indexName: 'theIndex2' }, - { indexName: 'theIndex3' }, - ], - }); - }); - - it('gracefully handles partial successes', async () => { - mockReindexService.createReindexOperation - .mockResolvedValueOnce({ - attributes: { indexName: 'theIndex1' }, - }) - .mockRejectedValueOnce(new Error('oops!')); - - mockReindexService.hasRequiredPrivileges - .mockResolvedValueOnce(true) - .mockResolvedValueOnce(false) - .mockResolvedValueOnce(true); - - const resp = await routeDependencies.router.getHandler({ - method: 'post', - pathPattern: '/api/upgrade_assistant/reindex/batch', - })( - routeHandlerContextMock, - createRequestMock({ body: { indexNames: ['theIndex1', 'theIndex2', 'theIndex3'] } }), - kibanaResponseFactory - ); - - // It called create correctly - expect(mockReindexService.createReindexOperation).toHaveBeenCalledTimes(2); - expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( - 1, - 'theIndex1', - queueSettingsArg - ); - expect(mockReindexService.createReindexOperation).toHaveBeenNthCalledWith( - 2, - 'theIndex3', - queueSettingsArg - ); - - // It returned the right results - expect(resp.status).toEqual(200); - const data = resp.payload; - expect(data).toEqual({ - errors: [ - { - indexName: 'theIndex2', - message: 'You do not have adequate privileges to reindex "theIndex2".', - }, - { indexName: 'theIndex3', message: 'oops!' }, - ], - enqueued: [{ indexName: 'theIndex1' }], - }); - }); - }); - describe('POST /api/upgrade_assistant/reindex/{indexName}/cancel', () => { it('returns a 501', async () => { mockReindexService.cancelReindexing.mockResolvedValueOnce({}); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts index 57ea99308e70f..23a5663edc00f 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts @@ -7,85 +7,14 @@ import { schema } from '@kbn/config-schema'; import { ResponseError } from '@elastic/elasticsearch/lib/errors'; -import { API_BASE_PATH } from '../../../common/constants'; -import { - ElasticsearchServiceStart, - kibanaResponseFactory, - Logger, - SavedObjectsClient, -} from '../../../../../../src/core/server'; - -import { LicensingPluginSetup } from '../../../../licensing/server'; -import { SecurityPluginStart } from '../../../../security/server'; - -import { ReindexStatus } from '../../../common/types'; +import { API_BASE_PATH } from '../../../common/constants'; import { versionCheckHandlerWrapper } from '../../lib/es_version_precheck'; import { reindexServiceFactory, ReindexWorker } from '../../lib/reindexing'; -import { CredentialStore } from '../../lib/reindexing/credential_store'; import { reindexActionsFactory } from '../../lib/reindexing/reindex_actions'; -import { sortAndOrderReindexOperations } from '../../lib/reindexing/op_utils'; -import { ReindexError } from '../../lib/reindexing/error'; import { RouteDependencies } from '../../types'; -import { - AccessForbidden, - CannotCreateIndex, - IndexNotFound, - MultipleReindexJobsFound, - ReindexAlreadyInProgress, - ReindexCannotBeCancelled, - ReindexTaskCannotBeDeleted, - ReindexTaskFailed, -} from '../../lib/reindexing/error_symbols'; - +import { mapAnyErrorToKibanaHttpResponse } from './map_any_error_to_kibana_http_response'; import { reindexHandler } from './reindex_handler'; -import { GetBatchQueueResponse, PostBatchResponse } from './types'; - -interface CreateReindexWorker { - logger: Logger; - elasticsearchService: ElasticsearchServiceStart; - credentialStore: CredentialStore; - savedObjects: SavedObjectsClient; - licensing: LicensingPluginSetup; - security: SecurityPluginStart; -} - -export function createReindexWorker({ - logger, - elasticsearchService, - credentialStore, - savedObjects, - licensing, - security, -}: CreateReindexWorker) { - const esClient = elasticsearchService.client; - return new ReindexWorker(savedObjects, credentialStore, esClient, logger, licensing, security); -} - -const mapAnyErrorToKibanaHttpResponse = (e: any) => { - if (e instanceof ReindexError) { - switch (e.symbol) { - case AccessForbidden: - return kibanaResponseFactory.forbidden({ body: e.message }); - case IndexNotFound: - return kibanaResponseFactory.notFound({ body: e.message }); - case CannotCreateIndex: - case ReindexTaskCannotBeDeleted: - throw e; - case ReindexTaskFailed: - // Bad data - return kibanaResponseFactory.customError({ body: e.message, statusCode: 422 }); - case ReindexAlreadyInProgress: - case MultipleReindexJobsFound: - case ReindexCannotBeCancelled: - return kibanaResponseFactory.badRequest({ body: e.message }); - default: - // nothing matched - } - } - - throw e; -}; export function registerReindexIndicesRoutes( { @@ -150,103 +79,6 @@ export function registerReindexIndicesRoutes( ) ); - // Get the current batch queue - router.get( - { - path: `${BASE_PATH}/batch/queue`, - validate: {}, - }, - async ( - { - core: { - elasticsearch: { client: esClient }, - savedObjects, - }, - }, - request, - response - ) => { - const { client } = savedObjects; - const callAsCurrentUser = esClient.asCurrentUser; - const reindexActions = reindexActionsFactory(client, callAsCurrentUser); - try { - const inProgressOps = await reindexActions.findAllByStatus(ReindexStatus.inProgress); - const { queue } = sortAndOrderReindexOperations(inProgressOps); - const result: GetBatchQueueResponse = { - queue: queue.map((savedObject) => savedObject.attributes), - }; - return response.ok({ - body: result, - }); - } catch (error) { - if (error instanceof ResponseError) { - return handleEsError({ error, response }); - } - return mapAnyErrorToKibanaHttpResponse(error); - } - } - ); - - // Add indices for reindexing to the worker's batch - router.post( - { - path: `${BASE_PATH}/batch`, - validate: { - body: schema.object({ - indexNames: schema.arrayOf(schema.string()), - }), - }, - }, - versionCheckHandlerWrapper( - async ( - { - core: { - savedObjects: { client: savedObjectsClient }, - elasticsearch: { client: esClient }, - }, - }, - request, - response - ) => { - const { indexNames } = request.body; - const results: PostBatchResponse = { - enqueued: [], - errors: [], - }; - for (const indexName of indexNames) { - try { - const result = await reindexHandler({ - savedObjects: savedObjectsClient, - dataClient: esClient, - indexName, - log, - licensing, - request, - credentialStore, - reindexOptions: { - enqueue: true, - }, - security: getSecurityPlugin(), - }); - results.enqueued.push(result); - } catch (e) { - results.errors.push({ - indexName, - message: e.message, - }); - } - } - - if (results.errors.length < indexNames.length) { - // Kick the worker on this node to immediately pickup the batch. - getWorker().forceRefresh(); - } - - return response.ok({ body: results }); - } - ) - ); - // Get status router.get( { From dae94b1536ebe2412b293636f35d92ce9c4ff9c0 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 6 Oct 2021 07:28:10 +0100 Subject: [PATCH 51/93] [Upgrade Assistant] Remove ML/Watcher logic (#113224) --- .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - .../reindex_deprecation_flyout.test.ts | 1 - .../plugins/upgrade_assistant/common/types.ts | 7 - .../reindex/flyout/progress.test.tsx | 78 +-- .../reindex/flyout/progress.tsx | 45 +- .../reindex/use_reindex_state.tsx | 9 +- .../lib/reindexing/reindex_actions.test.ts | 43 -- .../server/lib/reindexing/reindex_actions.ts | 109 +--- .../lib/reindexing/reindex_service.test.ts | 595 +----------------- .../server/lib/reindexing/reindex_service.ts | 175 +----- .../reindex_indices/reindex_indices.test.ts | 23 +- .../routes/reindex_indices/reindex_indices.ts | 2 - 13 files changed, 22 insertions(+), 1073 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4f978b2207ba5..a0ff61f13ee3d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25183,12 +25183,8 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancellingLabel": "キャンセル中…", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.errorLabel": "キャンセルできませんでした", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.createIndexStepTitle": "新規インデックスを作成中", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.pauseMlStepTitle": "機械学習ジョブを一時停止中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.readonlyStepTitle": "古いインデックスを読み込み専用に設定中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.reindexingDocumentsStepTitle": "ドキュメントを再インデックス中", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.resumeMlStepTitle": "機械学習ジョブを再開中", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.resumeWatcherStepTitle": "Watcher を再開中", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.stopWatcherStepTitle": "Watcher を停止中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklistTitle": "プロセスを再インデックス中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails": "このインデックスは現在閉じています。アップグレードアシスタントが開き、再インデックスを実行してからインデックスを閉じます。 {reindexingMayTakeLongerEmph}。詳細については {docs} をご覧ください。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails.reindexingTakesLongerEmphasis": "再インデックスには通常よりも時間がかかることがあります", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 15af05e9c5143..c497c81630507 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25612,12 +25612,8 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancellingLabel": "正在取消……", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.errorLabel": "无法取消", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.createIndexStepTitle": "正在创建新索引", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.pauseMlStepTitle": "正在暂停 Machine Learning 作业", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.readonlyStepTitle": "正在将旧索引设置为只读", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.reindexingDocumentsStepTitle": "正在重新索引文档", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.resumeMlStepTitle": "正在恢复 Machine Learning 作业", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.resumeWatcherStepTitle": "正在恢复 Watcher", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.stopWatcherStepTitle": "正在停止 Watcher", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklistTitle": "重新索引过程", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails": "此索引当前已关闭。升级助手将打开索引,重新索引,然后关闭索引。{reindexingMayTakeLongerEmph}。请参阅文档{docs}以了解更多信息。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails.reindexingTakesLongerEmphasis": "重新索引可能比通常花费更多的时间", diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts index dce2fa6e18ac9..ca9253c1140b0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts @@ -52,7 +52,6 @@ describe('Reindex deprecation flyout', () => { httpRequestsMockHelpers.setReindexStatusResponse({ reindexOp: null, warnings: [], - indexGroup: null, hasRequiredPrivileges: true, }); diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 3a539dba32b49..f955aa05288e3 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -13,13 +13,11 @@ export type DeprecationSource = 'Kibana' | 'Elasticsearch'; export enum ReindexStep { // Enum values are spaced out by 10 to give us room to insert steps in between. created = 0, - indexGroupServicesStopped = 10, readonly = 20, newIndexCreated = 30, reindexStarted = 40, reindexCompleted = 50, aliasCreated = 60, - indexGroupServicesStarted = 70, } export enum ReindexStatus { @@ -114,11 +112,6 @@ export interface ReindexWarning { }; } -export enum IndexGroup { - ml = '___ML_REINDEX_LOCK___', - watcher = '___WATCHER_REINDEX_LOCK___', -} - // Telemetry types export const UPGRADE_ASSISTANT_TYPE = 'upgrade-assistant-telemetry'; export const UPGRADE_ASSISTANT_DOC_ID = 'upgrade-assistant-telemetry'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx index b49d816302213..c58230b3563f3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx @@ -8,7 +8,7 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { IndexGroup, ReindexStatus, ReindexStep } from '../../../../../../../common/types'; +import { ReindexStatus, ReindexStep } from '../../../../../../../common/types'; import type { ReindexState } from '../use_reindex_state'; import { ReindexProgress } from './progress'; @@ -33,7 +33,7 @@ describe('ReindexProgress', () => { steps={ Array [ Object { - "status": "incomplete", + "status": "inProgress", "title": { expect(reindexStep.children.type.name).toEqual('ReindexProgressBar'); expect(reindexStep.children.props.reindexState.reindexTaskPercComplete).toEqual(0.25); }); - - it('adds steps for index groups', () => { - const wrapper = shallow( - - ); - - expect(wrapper).toMatchInlineSnapshot(` -, - }, - Object { - "status": "incomplete", - "title": , - }, - Object { - "status": "incomplete", - "title": , - }, - Object { - "status": "incomplete", - "title": , - }, - Object { - "status": "incomplete", - "title": , - }, - Object { - "status": "incomplete", - "title": , - }, - ] - } -/> -`); - }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx index 65a790fe96691..7a2c9943691a3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { IndexGroup, ReindexStatus, ReindexStep } from '../../../../../../../common/types'; +import { ReindexStatus, ReindexStep } from '../../../../../../../common/types'; import { LoadingState } from '../../../../types'; import type { ReindexState } from '../use_reindex_state'; import { StepProgress, StepProgressStep } from './step_progress'; @@ -118,7 +118,7 @@ export const ReindexProgress: React.FunctionComponent<{ reindexState: ReindexState; cancelReindex: () => void; }> = (props) => { - const { errorMessage, indexGroup, lastCompletedStep = -1, status } = props.reindexState; + const { errorMessage, lastCompletedStep = -1, status } = props.reindexState; const stepDetails = (thisStep: ReindexStep): Pick => { const previousStep = orderedSteps[orderedSteps.indexOf(thisStep) - 1]; @@ -225,46 +225,5 @@ export const ReindexProgress: React.FunctionComponent<{ }, ]; - // If this index is part of an index group, add the approriate group services steps. - if (indexGroup === IndexGroup.ml) { - steps.unshift({ - title: ( - - ), - ...stepDetails(ReindexStep.indexGroupServicesStopped), - }); - steps.push({ - title: ( - - ), - ...stepDetails(ReindexStep.indexGroupServicesStarted), - }); - } else if (indexGroup === IndexGroup.watcher) { - steps.unshift({ - title: ( - - ), - ...stepDetails(ReindexStep.indexGroupServicesStopped), - }); - steps.push({ - title: ( - - ), - ...stepDetails(ReindexStep.indexGroupServicesStarted), - }); - } - return ; }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index 87891c5d8d219..32a6c75ff6eec 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -8,7 +8,6 @@ import { useRef, useCallback, useState, useEffect } from 'react'; import { - IndexGroup, ReindexOperation, ReindexStatus, ReindexStep, @@ -28,19 +27,17 @@ export interface ReindexState { errorMessage: string | null; reindexWarnings?: ReindexWarning[]; hasRequiredPrivileges?: boolean; - indexGroup?: IndexGroup; } interface StatusResponse { warnings?: ReindexWarning[]; reindexOp?: ReindexOperation; hasRequiredPrivileges?: boolean; - indexGroup?: IndexGroup; } const getReindexState = ( reindexState: ReindexState, - { reindexOp, warnings, hasRequiredPrivileges, indexGroup }: StatusResponse + { reindexOp, warnings, hasRequiredPrivileges }: StatusResponse ) => { const newReindexState = { ...reindexState, @@ -55,10 +52,6 @@ const getReindexState = ( newReindexState.hasRequiredPrivileges = hasRequiredPrivileges; } - if (indexGroup) { - newReindexState.indexGroup = indexGroup; - } - if (reindexOp) { // Prevent the UI flickering back to inProgress after cancelling newReindexState.lastCompletedStep = reindexOp.lastCompletedStep; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts index 7595e1da7b573..3f58a04949da5 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts @@ -13,7 +13,6 @@ import { ScopedClusterClientMock } from 'src/core/server/elasticsearch/client/mo import moment from 'moment'; import { - IndexGroup, REINDEX_OP_TYPE, ReindexSavedObject, ReindexStatus, @@ -283,46 +282,4 @@ describe('ReindexActions', () => { await expect(actions.getFlatSettings('myIndex')).resolves.toBeNull(); }); }); - - describe('runWhileConsumerLocked', () => { - Object.entries(IndexGroup).forEach(([typeKey, consumerType]) => { - describe(`IndexConsumerType.${typeKey}`, () => { - it('creates the lock doc if it does not exist and executes callback', async () => { - expect.assertions(3); - client.get.mockRejectedValueOnce(SavedObjectsErrorHelpers.createGenericNotFoundError()); // mock no ML doc exists yet - client.create.mockImplementationOnce((type: any, attributes: any, { id }: any) => - Promise.resolve({ - type, - id, - attributes, - }) - ); - - let flip = false; - await actions.runWhileIndexGroupLocked(consumerType, async (mlDoc) => { - expect(mlDoc.id).toEqual(consumerType); - expect(mlDoc.attributes.runningReindexCount).toEqual(0); - flip = true; - return mlDoc; - }); - expect(flip).toEqual(true); - }); - - it('fails after 10 attempts to lock', async () => { - client.get.mockResolvedValue({ - type: REINDEX_OP_TYPE, - id: consumerType, - attributes: { mlReindexCount: 0 }, - }); - - client.update.mockRejectedValue(new Error('NO LOCKING!')); - - await expect( - actions.runWhileIndexGroupLocked(consumerType, async (m) => m) - ).rejects.toThrow('Could not acquire lock for ML jobs'); - expect(client.update).toHaveBeenCalledTimes(10); - }, 20000); - }); - }); - }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts index fe8844b28e37a..09ba4b744e68e 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts @@ -13,7 +13,6 @@ import { ElasticsearchClient, } from 'src/core/server'; import { - IndexGroup, REINDEX_OP_TYPE, ReindexOperation, ReindexOptions, @@ -33,11 +32,6 @@ export const LOCK_WINDOW = moment.duration(90, 'seconds'); * This is NOT intended to be used by any other code. */ export interface ReindexActions { - /** - * Namespace for ML-specific actions. - */ - // ml: MlActions; - /** * Creates a new reindexOp, does not perform any pre-flight checks. * @param indexName @@ -86,34 +80,10 @@ export interface ReindexActions { * Retrieve index settings (in flat, dot-notation style) and mappings. * @param indexName */ - getFlatSettings(indexName: string): Promise; - - // ----- Functions below are for enforcing locks around groups of indices like ML or Watcher - - /** - * Atomically increments the number of reindex operations running for an index group. - */ - incrementIndexGroupReindexes(group: IndexGroup): Promise; - - /** - * Atomically decrements the number of reindex operations running for an index group. - */ - decrementIndexGroupReindexes(group: IndexGroup): Promise; - - /** - * Runs a callback function while locking an index group. - * @param func A function to run with the locked index group lock document. Must return a promise that resolves - * to the updated ReindexSavedObject. - */ - runWhileIndexGroupLocked( - group: IndexGroup, - func: (lockDoc: ReindexSavedObject) => Promise - ): Promise; - - /** - * Exposed only for testing, DO NOT USE. - */ - _fetchAndLockIndexGroupDoc(group: IndexGroup): Promise; + getFlatSettings( + indexName: string, + withTypeName?: boolean + ): Promise; } export const reindexActionsFactory = ( @@ -266,76 +236,5 @@ export const reindexActionsFactory = ( return flatSettings.body[indexName]; }, - - async _fetchAndLockIndexGroupDoc(indexGroup) { - const fetchDoc = async () => { - try { - // The IndexGroup enum value (a string) serves as the ID of the lock doc - return await client.get(REINDEX_OP_TYPE, indexGroup); - } catch (e) { - if (client.errors.isNotFoundError(e)) { - return await client.create( - REINDEX_OP_TYPE, - { - indexName: null, - newIndexName: null, - locked: null, - status: null, - lastCompletedStep: null, - reindexTaskId: null, - reindexTaskPercComplete: null, - errorMessage: null, - runningReindexCount: 0, - } as any, - { id: indexGroup } - ); - } else { - throw e; - } - } - }; - - const lockDoc = async (attempt = 1): Promise => { - try { - // Refetch the document each time to avoid version conflicts. - return await acquireLock(await fetchDoc()); - } catch (e) { - if (attempt >= 10) { - throw new Error(`Could not acquire lock for ML jobs`); - } - - await new Promise((resolve) => setTimeout(resolve, 1000)); - return lockDoc(attempt + 1); - } - }; - - return lockDoc(); - }, - - async incrementIndexGroupReindexes(indexGroup) { - this.runWhileIndexGroupLocked(indexGroup, (lockDoc) => - this.updateReindexOp(lockDoc, { - runningReindexCount: lockDoc.attributes.runningReindexCount! + 1, - }) - ); - }, - - async decrementIndexGroupReindexes(indexGroup) { - this.runWhileIndexGroupLocked(indexGroup, (lockDoc) => - this.updateReindexOp(lockDoc, { - runningReindexCount: lockDoc.attributes.runningReindexCount! - 1, - }) - ); - }, - - async runWhileIndexGroupLocked(indexGroup, func) { - let lockDoc = await this._fetchAndLockIndexGroupDoc(indexGroup); - - try { - lockDoc = await func(lockDoc); - } finally { - await releaseLock(lockDoc); - } - }, }; }; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index bd31196dbb78b..bc66c63471656 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -7,14 +7,13 @@ jest.mock('../es_indices_state_check', () => ({ esIndicesStateCheck: jest.fn() })); import { BehaviorSubject } from 'rxjs'; -import { TransportResult } from '@elastic/elasticsearch'; +import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; import { Logger } from 'src/core/server'; import { elasticsearchServiceMock, loggingSystemMock } from 'src/core/server/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ScopedClusterClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { - IndexGroup, ReindexOperation, ReindexSavedObject, ReindexStatus, @@ -28,17 +27,12 @@ import { getMockVersionInfo } from '../__fixtures__/version'; import { esIndicesStateCheck } from '../es_indices_state_check'; import { versionService } from '../version'; -import { - isMlIndex, - isWatcherIndex, - ReindexService, - reindexServiceFactory, -} from './reindex_service'; +import { ReindexService, reindexServiceFactory } from './reindex_service'; -const asApiResponse = (body: T): TransportResult => +const asApiResponse = (body: T): RequestEvent => ({ body, - } as TransportResult); + } as RequestEvent); const { currentMajor, prevMajor } = getMockVersionInfo(); @@ -69,9 +63,6 @@ describe('reindexService', () => { findAllByStatus: jest.fn(unimplemented('findAllInProgressOperations')), getFlatSettings: jest.fn(unimplemented('getFlatSettings')), cleanupChanges: jest.fn(), - incrementIndexGroupReindexes: jest.fn(unimplemented('incrementIndexGroupReindexes')), - decrementIndexGroupReindexes: jest.fn(unimplemented('decrementIndexGroupReindexes')), - runWhileIndexGroupLocked: jest.fn(async (group: string, f: any) => f({ attributes: {} })), }; clusterClient = elasticsearchServiceMock.createScopedClusterClient(); log = loggingSystemMock.create().get(); @@ -129,31 +120,6 @@ describe('reindexService', () => { }); }); - it('includes manage_ml for ML indices', async () => { - clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( - // @ts-expect-error not full interface - asApiResponse({ has_all_requested: true }) - ); - - await service.hasRequiredPrivileges('.ml-anomalies'); - expect(clusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({ - body: { - cluster: ['manage', 'manage_ml'], - index: [ - { - names: ['.ml-anomalies', `.reindexed-v${currentMajor}-ml-anomalies`], - allow_restricted_indices: true, - privileges: ['all'], - }, - { - names: ['.tasks'], - privileges: ['read', 'delete'], - }, - ], - }, - }); - }); - it('includes checking for permissions on the baseName which could be an alias', async () => { clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( // @ts-expect-error not full interface @@ -183,33 +149,6 @@ describe('reindexService', () => { }, }); }); - - it('includes manage_watcher for watcher indices', async () => { - clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( - // @ts-expect-error not full interface - asApiResponse({ - has_all_requested: true, - }) - ); - - await service.hasRequiredPrivileges('.watches'); - expect(clusterClient.asCurrentUser.security.hasPrivileges).toHaveBeenCalledWith({ - body: { - cluster: ['manage', 'manage_watcher'], - index: [ - { - names: ['.watches', `.reindexed-v${currentMajor}-watches`], - allow_restricted_indices: true, - privileges: ['all'], - }, - { - names: ['.tasks'], - privileges: ['read', 'delete'], - }, - ], - }, - }); - }); }); describe('detectReindexWarnings', () => { @@ -496,40 +435,6 @@ describe('reindexService', () => { }); }); - describe('isMlIndex', () => { - it('is false for non-ml indices', () => { - expect(isMlIndex('.literally-anything')).toBe(false); - }); - - it('is true for ML indices', () => { - expect(isMlIndex('.ml-state')).toBe(true); - expect(isMlIndex('.ml-anomalies')).toBe(true); - expect(isMlIndex('.ml-config')).toBe(true); - }); - - it('is true for ML re-indexed indices', () => { - expect(isMlIndex(`.reindexed-v${prevMajor}-ml-state`)).toBe(true); - expect(isMlIndex(`.reindexed-v${prevMajor}-ml-anomalies`)).toBe(true); - expect(isMlIndex(`.reindexed-v${prevMajor}-ml-config`)).toBe(true); - }); - }); - - describe('isWatcherIndex', () => { - it('is false for non-watcher indices', () => { - expect(isWatcherIndex('.literally-anything')).toBe(false); - }); - - it('is true for watcher indices', () => { - expect(isWatcherIndex('.watches')).toBe(true); - expect(isWatcherIndex('.triggered-watches')).toBe(true); - }); - - it('is true for watcher re-indexed indices', () => { - expect(isWatcherIndex(`.reindexed-v${prevMajor}-watches`)).toBe(true); - expect(isWatcherIndex(`.reindexed-v${prevMajor}-triggered-watches`)).toBe(true); - }); - }); - describe('state machine, lastCompletedStep ===', () => { const defaultAttributes = { indexName: 'myIndex', @@ -541,287 +446,6 @@ describe('reindexService', () => { mappings: { _doc: { properties: { timestampl: { type: 'date' } } } }, }; - describe('created', () => { - const reindexOp = { - id: '1', - attributes: { ...defaultAttributes, lastCompletedStep: ReindexStep.created }, - } as ReindexSavedObject; - - describe('ml behavior', () => { - const mlReindexOp = { - id: '2', - attributes: { ...reindexOp.attributes, indexName: '.ml-anomalies' }, - } as ReindexSavedObject; - - it('does nothing if index is not an ML index', async () => { - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStopped - ); - expect(actions.incrementIndexGroupReindexes).not.toHaveBeenCalled(); - expect(actions.runWhileIndexGroupLocked).not.toHaveBeenCalled(); - expect(clusterClient.asCurrentUser.nodes.info).not.toHaveBeenCalled(); - }); - - it('supports an already migrated ML index', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f() - ); - clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( - // @ts-expect-error not full interface - asApiResponse({ nodes: { nodeX: { version: '6.7.0-alpha' } } }) - ); - clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - - const mlReindexedOp = { - id: '2', - attributes: { - ...reindexOp.attributes, - indexName: `.reindexed-v${prevMajor}-ml-anomalies`, - }, - } as ReindexSavedObject; - const updatedOp = await service.processNextStep(mlReindexedOp); - - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStopped - ); - expect(actions.incrementIndexGroupReindexes).toHaveBeenCalled(); - expect(actions.runWhileIndexGroupLocked).toHaveBeenCalled(); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ - enabled: true, - }); - }); - - it('increments ML reindexes and calls ML stop endpoint', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f() - ); - - clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( - // @ts-expect-error not full interface - asApiResponse({ nodes: { nodeX: { version: '6.7.0-alpha' } } }) - ); - clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStopped - ); - expect(actions.incrementIndexGroupReindexes).toHaveBeenCalled(); - expect(actions.runWhileIndexGroupLocked).toHaveBeenCalled(); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ - enabled: true, - }); - }); - - it('fails if ML reindexes cannot be incremented', async () => { - actions.incrementIndexGroupReindexes.mockRejectedValueOnce(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ - enabled: true, - }); - }); - - it('fails if ML doc cannot be locked', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockRejectedValueOnce(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ - enabled: true, - }); - }); - - it('fails if ML endpoint fails', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f() - ); - clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( - // @ts-expect-error not full interface - asApiResponse({ nodes: { nodeX: { version: '6.7.0' } } }) - ); - clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( - asApiResponse({ acknowledged: false }) - ); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect( - updatedOp.attributes.errorMessage!.includes('Could not stop ML jobs') - ).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ - enabled: true, - }); - }); - - it('fails if not all nodes have been upgraded to 6.7.0', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f() - ); - clusterClient.asCurrentUser.nodes.info.mockResolvedValueOnce( - // @ts-expect-error not full interface - asApiResponse({ nodes: { nodeX: { version: '6.6.0' } } }) - ); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect( - updatedOp.attributes.errorMessage!.includes('Some nodes are not on minimum version') - ).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - // Should not have called ML endpoint at all - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ - enabled: true, - }); - }); - }); - - describe('watcher behavior', () => { - const watcherReindexOp = { - id: '2', - attributes: { ...reindexOp.attributes, indexName: '.watches' }, - } as ReindexSavedObject; - - it('does nothing if index is not a watcher index', async () => { - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStopped - ); - expect(actions.incrementIndexGroupReindexes).not.toHaveBeenCalled(); - expect(actions.runWhileIndexGroupLocked).not.toHaveBeenCalled(); - expect(clusterClient.asCurrentUser.watcher.stop).not.toHaveBeenCalled(); - }); - - it('increments ML reindexes and calls watcher stop endpoint', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (type: string, f: any) => - f() - ); - clusterClient.asCurrentUser.watcher.stop.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStopped - ); - expect(actions.incrementIndexGroupReindexes).toHaveBeenCalledWith(IndexGroup.watcher); - expect(actions.runWhileIndexGroupLocked).toHaveBeenCalled(); - expect(clusterClient.asCurrentUser.watcher.stop).toHaveBeenCalled(); - }); - - it('fails if watcher reindexes cannot be incremented', async () => { - actions.incrementIndexGroupReindexes.mockRejectedValueOnce(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.watcher.stop).not.toHaveBeenCalledWith({ - enabled: true, - }); - }); - - it('fails if watcher doc cannot be locked', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockRejectedValueOnce(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.watcher.stop).not.toHaveBeenCalled(); - }); - - it('fails if watcher endpoint fails', async () => { - actions.incrementIndexGroupReindexes.mockResolvedValueOnce(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (type: string, f: any) => - f() - ); - clusterClient.asCurrentUser.watcher.stop.mockResolvedValueOnce( - asApiResponse({ acknowledged: false }) - ); - - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect( - updatedOp.attributes.errorMessage!.includes('Could not stop Watcher') - ).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.watcher.stop).toHaveBeenCalled(); - }); - }); - }); - - describe('indexConsumersStopped', () => { - const reindexOp = { - id: '1', - attributes: { - ...defaultAttributes, - lastCompletedStep: ReindexStep.indexGroupServicesStopped, - }, - } as ReindexSavedObject; - - it('blocks writes and updates lastCompletedStep', async () => { - clusterClient.asCurrentUser.indices.putSettings.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.readonly); - expect(clusterClient.asCurrentUser.indices.putSettings).toHaveBeenCalledWith({ - index: 'myIndex', - body: { blocks: { write: true } }, - }); - }); - - it('fails if setting updates are not acknowledged', async () => { - clusterClient.asCurrentUser.indices.putSettings.mockResolvedValueOnce( - asApiResponse({ acknowledged: false }) - ); - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStopped - ); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - }); - - it('fails if setting updates fail', async () => { - clusterClient.asCurrentUser.indices.putSettings.mockRejectedValueOnce(new Error('blah!')); - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStopped - ); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - }); - }); - describe('readonly', () => { const reindexOp = { id: '1', @@ -885,7 +509,7 @@ describe('reindexService', () => { // Original index should have been set back to allow reads. expect(clusterClient.asCurrentUser.indices.putSettings).toHaveBeenCalledWith({ index: 'myIndex', - body: { blocks: { write: false } }, + body: { settings: { blocks: { write: false } } }, }); }); }); @@ -1129,216 +753,19 @@ describe('reindexService', () => { }); describe('aliasCreated', () => { - const reindexOp = { - id: '1', - attributes: { ...defaultAttributes, lastCompletedStep: ReindexStep.aliasCreated }, - } as ReindexSavedObject; - - describe('ml behavior', () => { - const mlReindexOp = { - id: '2', - attributes: { ...reindexOp.attributes, indexName: '.ml-anomalies' }, - } as ReindexSavedObject; - - it('does nothing if index is not an ML index', async () => { - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStarted - ); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalled(); - }); - - it('decrements ML reindexes and calls ML start endpoint if no remaining ML jobs', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f({ attributes: { runningReindexCount: 0 } }) - ); - clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(actions.decrementIndexGroupReindexes).toHaveBeenCalledWith(IndexGroup.ml); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStarted - ); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ - enabled: false, - }); - }); - - it('does not call ML start endpoint if there are remaining ML jobs', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f({ attributes: { runningReindexCount: 2 } }) - ); - clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStarted - ); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ - enabled: false, - }); - }); - - it('fails if ML reindexes cannot be decremented', async () => { - // Mock unable to lock ml doc - actions.decrementIndexGroupReindexes.mockRejectedValue(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ - enabled: false, - }); - }); - - it('fails if ML doc cannot be locked', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - // Mock unable to lock ml doc - actions.runWhileIndexGroupLocked.mockRejectedValueOnce(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).not.toHaveBeenCalledWith({ - enabled: false, - }); - }); - - it('fails if ML endpoint fails', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f({ attributes: { runningReindexCount: 0 } }) - ); - clusterClient.asCurrentUser.ml.setUpgradeMode.mockResolvedValueOnce( - asApiResponse({ acknowledged: false }) - ); - const updatedOp = await service.processNextStep(mlReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect( - updatedOp.attributes.errorMessage!.includes('Could not resume ML jobs') - ).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.ml.setUpgradeMode).toHaveBeenCalledWith({ - enabled: false, - }); - }); - }); - - describe('watcher behavior', () => { - const watcherReindexOp = { - id: '2', - attributes: { ...reindexOp.attributes, indexName: '.watches' }, - } as ReindexSavedObject; - - it('does nothing if index is not a watcher index', async () => { - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStarted - ); - expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalled(); - }); - - it('decrements watcher reindexes and calls wathcer start endpoint if no remaining watcher reindexes', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f({ attributes: { runningReindexCount: 0 } }) - ); - clusterClient.asCurrentUser.watcher.start.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(actions.decrementIndexGroupReindexes).toHaveBeenCalledWith(IndexGroup.watcher); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStarted - ); - expect(clusterClient.asCurrentUser.watcher.start).toHaveBeenCalled(); - }); - - it('does not call watcher start endpoint if there are remaining watcher reindexes', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f({ attributes: { runningReindexCount: 2 } }) - ); - clusterClient.asCurrentUser.watcher.start.mockResolvedValueOnce( - asApiResponse({ acknowledged: true }) - ); - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual( - ReindexStep.indexGroupServicesStarted - ); - expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalledWith(); - }); - - it('fails if watcher reindexes cannot be decremented', async () => { - // Mock unable to lock watcher doc - actions.decrementIndexGroupReindexes.mockRejectedValue(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalledWith(); - }); - - it('fails if watcher doc cannot be locked', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - // Mock unable to lock watcher doc - actions.runWhileIndexGroupLocked.mockRejectedValueOnce(new Error(`Can't lock!`)); - - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.watcher.start).not.toHaveBeenCalledWith(); - }); - - it('fails if watcher endpoint fails', async () => { - actions.decrementIndexGroupReindexes.mockResolvedValue(); - actions.runWhileIndexGroupLocked.mockImplementationOnce(async (group: string, f: any) => - f({ attributes: { runningReindexCount: 0 } }) - ); - - clusterClient.asCurrentUser.watcher.start.mockResolvedValueOnce( - asApiResponse({ acknowledged: false }) - ); - const updatedOp = await service.processNextStep(watcherReindexOp); - expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); - expect( - updatedOp.attributes.errorMessage!.includes('Could not start Watcher') - ).toBeTruthy(); - expect(log.error).toHaveBeenCalledWith(expect.any(String)); - expect(clusterClient.asCurrentUser.watcher.start).toHaveBeenCalled(); - }); - }); - }); - - describe('indexGroupServicesStarted', () => { const reindexOp = { id: '1', attributes: { ...defaultAttributes, - lastCompletedStep: ReindexStep.indexGroupServicesStarted, + lastCompletedStep: ReindexStep.aliasCreated, }, } as ReindexSavedObject; - it('sets to completed', async () => { - const updatedOp = await service.processNextStep(reindexOp); - expect(updatedOp.attributes.status).toEqual(ReindexStatus.completed); + it('sets reindex status as complete', async () => { + await service.processNextStep(reindexOp); + expect(actions.updateReindexOp).toHaveBeenCalledWith(reindexOp, { + status: ReindexStatus.completed, + }); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts index 77b5495bd4563..f9db1692ab1b7 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts @@ -11,7 +11,6 @@ import { first } from 'rxjs/operators'; import { LicensingPluginSetup } from '../../../../licensing/server'; import { - IndexGroup, ReindexSavedObject, ReindexStatus, ReindexStep, @@ -31,10 +30,6 @@ import { ReindexActions } from './reindex_actions'; import { error } from './error'; -const VERSION_REGEX = new RegExp(/^([1-9]+)\.([0-9]+)\.([0-9]+)/); -const ML_INDICES = ['.ml-state', '.ml-anomalies', '.ml-config']; -const WATCHER_INDICES = ['.watches', '.triggered-watches']; - export interface ReindexService { /** * Checks whether or not the user has proper privileges required to reindex this index. @@ -49,12 +44,6 @@ export interface ReindexService { */ detectReindexWarnings(indexName: string): Promise; - /** - * Returns an IndexGroup if the index belongs to one, otherwise undefined. - * @param indexName - */ - getIndexGroup(indexName: string): IndexGroup | undefined; - /** * Creates a new reindex operation for a given index. * @param indexName @@ -135,83 +124,6 @@ export const reindexServiceFactory = ( licensing: LicensingPluginSetup ): ReindexService => { // ------ Utility functions - - /** - * If the index is a ML index that will cause jobs to fail when set to readonly, - * turn on 'upgrade mode' to pause all ML jobs. - * @param reindexOp - */ - const stopMlJobs = async () => { - await actions.incrementIndexGroupReindexes(IndexGroup.ml); - await actions.runWhileIndexGroupLocked(IndexGroup.ml, async (mlDoc) => { - await validateNodesMinimumVersion(6, 7); - - const { body } = await esClient.ml.setUpgradeMode({ - enabled: true, - }); - - if (!body.acknowledged) { - throw new Error(`Could not stop ML jobs`); - } - - return mlDoc; - }); - }; - - /** - * Resumes ML jobs if there are no more remaining reindex operations. - */ - const resumeMlJobs = async () => { - await actions.decrementIndexGroupReindexes(IndexGroup.ml); - await actions.runWhileIndexGroupLocked(IndexGroup.ml, async (mlDoc) => { - if (mlDoc.attributes.runningReindexCount === 0) { - const { body } = await esClient.ml.setUpgradeMode({ - enabled: false, - }); - - if (!body.acknowledged) { - throw new Error(`Could not resume ML jobs`); - } - } - - return mlDoc; - }); - }; - - /** - * Stops Watcher in Elasticsearch. - */ - const stopWatcher = async () => { - await actions.incrementIndexGroupReindexes(IndexGroup.watcher); - await actions.runWhileIndexGroupLocked(IndexGroup.watcher, async (watcherDoc) => { - const { body } = await esClient.watcher.stop(); - - if (!body.acknowledged) { - throw new Error('Could not stop Watcher'); - } - - return watcherDoc; - }); - }; - - /** - * Starts Watcher in Elasticsearch. - */ - const startWatcher = async () => { - await actions.decrementIndexGroupReindexes(IndexGroup.watcher); - await actions.runWhileIndexGroupLocked(IndexGroup.watcher, async (watcherDoc) => { - if (watcherDoc.attributes.runningReindexCount === 0) { - const { body } = await esClient.watcher.start(); - - if (!body.acknowledged) { - throw new Error('Could not start Watcher'); - } - } - - return watcherDoc; - }); - }; - const cleanupChanges = async (reindexOp: ReindexSavedObject) => { // Cancel reindex task if it was started but not completed if (reindexOp.attributes.lastCompletedStep === ReindexStep.reindexStarted) { @@ -239,48 +151,11 @@ export const reindexServiceFactory = ( }); } - // Resume consumers if we ever got past this point. - if (reindexOp.attributes.lastCompletedStep >= ReindexStep.indexGroupServicesStopped) { - await resumeIndexGroupServices(reindexOp); - } - return reindexOp; }; // ------ Functions used to process the state machine - const validateNodesMinimumVersion = async (minMajor: number, minMinor: number) => { - const { body: nodesResponse } = await esClient.nodes.info(); - - const outDatedNodes = Object.values(nodesResponse.nodes).filter((node: any) => { - const matches = node.version.match(VERSION_REGEX); - const major = parseInt(matches[1], 10); - const minor = parseInt(matches[2], 10); - - // All ES nodes must be >= 6.7.0 to pause ML jobs - return !(major > minMajor || (major === minMajor && minor >= minMinor)); - }); - - if (outDatedNodes.length > 0) { - const nodeList = JSON.stringify(outDatedNodes.map((n: any) => n.name)); - throw new Error( - `Some nodes are not on minimum version (${minMajor}.${minMinor}.0) required: ${nodeList}` - ); - } - }; - - const stopIndexGroupServices = async (reindexOp: ReindexSavedObject) => { - if (isMlIndex(reindexOp.attributes.indexName)) { - await stopMlJobs(); - } else if (isWatcherIndex(reindexOp.attributes.indexName)) { - await stopWatcher(); - } - - return actions.updateReindexOp(reindexOp, { - lastCompletedStep: ReindexStep.indexGroupServicesStopped, - }); - }; - /** * Sets the original index as readonly so new data can be indexed until the reindex * is completed. @@ -476,23 +351,6 @@ export const reindexServiceFactory = ( }); }; - const resumeIndexGroupServices = async (reindexOp: ReindexSavedObject) => { - if (isMlIndex(reindexOp.attributes.indexName)) { - await resumeMlJobs(); - } else if (isWatcherIndex(reindexOp.attributes.indexName)) { - await startWatcher(); - } - - // Only change the status if we're still in-progress (this function is also called when the reindex fails or is cancelled) - if (reindexOp.attributes.status === ReindexStatus.inProgress) { - return actions.updateReindexOp(reindexOp, { - lastCompletedStep: ReindexStep.indexGroupServicesStarted, - }); - } else { - return reindexOp; - } - }; - // ------ The service itself return { @@ -537,14 +395,6 @@ export const reindexServiceFactory = ( ], } as any; - if (isMlIndex(indexName)) { - body.cluster = [...body.cluster, 'manage_ml']; - } - - if (isWatcherIndex(indexName)) { - body.cluster = [...body.cluster, 'manage_watcher']; - } - const { body: resp } = await esClient.security.hasPrivileges({ body, }); @@ -561,14 +411,6 @@ export const reindexServiceFactory = ( } }, - getIndexGroup(indexName: string) { - if (isMlIndex(indexName)) { - return IndexGroup.ml; - } else if (isWatcherIndex(indexName)) { - return IndexGroup.watcher; - } - }, - async createReindexOperation(indexName: string, opts?: { enqueue: boolean }) { const { body: indexExists } = await esClient.indices.exists({ index: indexName }); if (!indexExists) { @@ -636,9 +478,6 @@ export const reindexServiceFactory = ( try { switch (lockedReindexOp.attributes.lastCompletedStep) { case ReindexStep.created: - lockedReindexOp = await stopIndexGroupServices(lockedReindexOp); - break; - case ReindexStep.indexGroupServicesStopped: lockedReindexOp = await setReadonly(lockedReindexOp); break; case ReindexStep.readonly: @@ -654,12 +493,10 @@ export const reindexServiceFactory = ( lockedReindexOp = await switchAlias(lockedReindexOp); break; case ReindexStep.aliasCreated: - lockedReindexOp = await resumeIndexGroupServices(lockedReindexOp); - break; - case ReindexStep.indexGroupServicesStarted: lockedReindexOp = await actions.updateReindexOp(lockedReindexOp, { status: ReindexStatus.completed, }); + break; default: break; } @@ -767,13 +604,3 @@ export const reindexServiceFactory = ( }, }; }; - -export const isMlIndex = (indexName: string) => { - const sourceName = sourceNameForIndex(indexName); - return ML_INDICES.indexOf(sourceName) >= 0; -}; - -export const isWatcherIndex = (indexName: string) => { - const sourceName = sourceNameForIndex(indexName); - return WATCHER_INDICES.indexOf(sourceName) >= 0; -}; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts index c510790800f64..9fcff5748a987 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts @@ -17,7 +17,6 @@ import { errors as esErrors } from '@elastic/elasticsearch'; const mockReindexService = { hasRequiredPrivileges: jest.fn(), detectReindexWarnings: jest.fn(), - getIndexGroup: jest.fn(), createReindexOperation: jest.fn(), findAllInProgressOperations: jest.fn(), findReindexOperation: jest.fn(), @@ -35,7 +34,7 @@ jest.mock('../../lib/reindexing', () => { }; }); -import { IndexGroup, ReindexSavedObject, ReindexStatus } from '../../../common/types'; +import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; import { credentialStoreFactory } from '../../lib/reindexing/credential_store'; import { registerReindexIndicesRoutes } from './reindex_indices'; @@ -69,7 +68,6 @@ describe('reindex API', () => { mockReindexService.hasRequiredPrivileges.mockResolvedValue(true); mockReindexService.detectReindexWarnings.mockReset(); - mockReindexService.getIndexGroup.mockReset(); mockReindexService.createReindexOperation.mockReset(); mockReindexService.findAllInProgressOperations.mockReset(); mockReindexService.findReindexOperation.mockReset(); @@ -164,25 +162,6 @@ describe('reindex API', () => { expect(data.reindexOp).toBeNull(); expect(data.warnings).toBeNull(); }); - - it('returns the indexGroup for ML indices', async () => { - mockReindexService.findReindexOperation.mockResolvedValueOnce(null); - mockReindexService.detectReindexWarnings.mockResolvedValueOnce([]); - mockReindexService.getIndexGroup.mockReturnValue(IndexGroup.ml); - - const resp = await routeDependencies.router.getHandler({ - method: 'get', - pathPattern: '/api/upgrade_assistant/reindex/{indexName}', - })( - routeHandlerContextMock, - createRequestMock({ params: { indexName: 'anIndex' } }), - kibanaResponseFactory - ); - - expect(resp.status).toEqual(200); - const data = resp.payload; - expect(data.indexGroup).toEqual(IndexGroup.ml); - }); }); describe('POST /api/upgrade_assistant/reindex/{indexName}', () => { diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts index 23a5663edc00f..f5fefe55379c7 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts @@ -113,13 +113,11 @@ export function registerReindexIndicesRoutes( const warnings = hasRequiredPrivileges ? await reindexService.detectReindexWarnings(indexName) : []; - const indexGroup = reindexService.getIndexGroup(indexName); return response.ok({ body: { reindexOp: reindexOp ? reindexOp.attributes : null, warnings, - indexGroup, hasRequiredPrivileges, }, }); From c47fa606351b4082b6182cc72ab1fa4e33f48d50 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 11 Oct 2021 18:16:44 +0100 Subject: [PATCH 52/93] Add show upgrade flag to url (#114243) --- .../overview/upgrade_step/upgrade_step.test.tsx | 2 +- .../components/overview/upgrade_step/upgrade_step.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx index 7135c5849fb73..601ed8992aa47 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/upgrade_step/upgrade_step.test.tsx @@ -53,7 +53,7 @@ describe('Overview - Upgrade Step', () => { expect(exists('upgradeSetupCloudLink')).toBe(true); expect(find('upgradeSetupCloudLink').props().href).toBe( - 'https://cloud.elastic.co./deployments/bfdad4ef99a24212a06d387593686d63' + 'https://cloud.elastic.co./deployments/bfdad4ef99a24212a06d387593686d63?show_upgrade=true' ); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx index dffdf39e5dd59..5acbf280e0b4e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx @@ -56,11 +56,12 @@ const UpgradeStep = ({ docLinks }: { docLinks: DocLinksStart }) => { let callToAction; if (isCloudEnabled) { + const upgradeOnCloudUrl = cloud!.deploymentUrl + '?show_upgrade=true'; callToAction = ( Date: Mon, 11 Oct 2021 18:17:52 +0100 Subject: [PATCH 53/93] [Upgrade Assistant] Delete deprecation log cache (#114113) --- .../helpers/http_requests.ts | 11 +++++ .../fix_logs_step/fix_logs_step.test.tsx | 43 +++++++++++++++++++ .../deprecations_count_checkpoint.tsx | 32 ++++++++++++-- .../public/application/lib/api.ts | 7 +++ .../server/routes/deprecation_logging.test.ts | 38 ++++++++++++++++ .../server/routes/deprecation_logging.ts | 29 +++++++++++++ 6 files changed, 156 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts index 448eb79152894..4f0e048da0792 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts @@ -69,6 +69,16 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setDeleteLogsCacheResponse = (response?: string, error?: ResponseError) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + server.respondWith('DELETE', `${API_BASE_PATH}/deprecation_logging/cache`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + const setUpdateDeprecationLoggingResponse = ( response?: DeprecationLoggingStatus, error?: ResponseError @@ -169,6 +179,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { setDeleteMlSnapshotResponse, setUpgradeMlSnapshotStatusResponse, setLoadDeprecationLogsCountResponse, + setDeleteLogsCacheResponse, setStartReindexingResponse, setReindexStatusResponse, setLoadMlUpgradeModeResponse, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index 7f58b36d29c36..7d4b6b8518dff 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -248,6 +248,7 @@ describe('Overview - Fix deprecation logs step', () => { describe('Step 3 - Resolve log issues', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadDeprecationLoggingResponse(getLoggingResponse(true)); + httpRequestsMockHelpers.setDeleteLogsCacheResponse('ok'); }); test('With deprecation warnings', async () => { @@ -337,6 +338,48 @@ describe('Overview - Fix deprecation logs step', () => { expect(exists('noWarningsCallout')).toBe(true); }); + test('Shows a toast if deleting cache fails', async () => { + const error = { + statusCode: 500, + error: 'Internal server error', + message: 'Internal server error', + }; + + httpRequestsMockHelpers.setDeleteLogsCacheResponse(undefined, error); + // Initially we want to have the callout to have a warning state + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ count: 10 }); + + const addDanger = jest.fn(); + await act(async () => { + testBed = await setupOverviewPage({ + services: { + core: { + notifications: { + toasts: { + addDanger, + }, + }, + }, + }, + }); + }); + + const { exists, actions, component } = testBed; + + component.update(); + + httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ count: 0 }); + + await actions.clickResetButton(); + + // The toast should always be shown if the delete logs cache fails. + expect(addDanger).toHaveBeenCalled(); + // Even though we changed the response of the getLogsCountResponse, when the + // deleteLogsCache fails the getLogsCount api should not be called and the + // status of the callout should remain the same it initially was. + expect(exists('hasWarningsCallout')).toBe(true); + }); + describe('Poll for logs count', () => { beforeEach(async () => { jest.useFakeTimers(); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx index 9717918e25a6d..c200884e94699 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent, useEffect } from 'react'; +import React, { FunctionComponent, useEffect, useState } from 'react'; import moment from 'moment-timezone'; import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; @@ -44,6 +44,9 @@ const i18nTexts = { defaultMessage: 'Reset counter', } ), + errorToastTitle: i18n.translate('xpack.upgradeAssistant.overview.verifyChanges.errorToastTitle', { + defaultMessage: 'Could not delete deprecation logs cache', + }), }; interface Props { @@ -57,8 +60,12 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ setCheckpoint, setHasNoDeprecationLogs, }) => { + const [isDeletingCache, setIsDeletingCache] = useState(false); const { - services: { api }, + services: { + api, + core: { notifications }, + }, } = useAppContext(); const { data, error, isLoading, resendRequest, isInitialRequest } = api.getDeprecationLogsCount( checkpoint @@ -70,7 +77,19 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ const calloutIcon = hasLogs ? 'alert' : 'check'; const calloutTestId = hasLogs ? 'hasWarningsCallout' : 'noWarningsCallout'; - const onResetClick = () => { + const onResetClick = async () => { + setIsDeletingCache(true); + const { error: deleteLogsCacheError } = await api.deleteDeprecationLogsCache(); + setIsDeletingCache(false); + + if (deleteLogsCacheError) { + notifications.toasts.addDanger({ + title: i18nTexts.errorToastTitle, + text: deleteLogsCacheError.message.toString(), + }); + return; + } + const now = moment().toISOString(); setCheckpoint(now); }; @@ -115,7 +134,12 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ data-test-subj={calloutTestId} >

{i18nTexts.calloutBody}

- + {i18nTexts.resetCounterButton} diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index da4f87f497467..b701a5a5eff2c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -106,6 +106,13 @@ export class ApiService { }); } + public deleteDeprecationLogsCache() { + return this.sendRequest({ + path: `${API_BASE_PATH}/deprecation_logging/cache`, + method: 'delete', + }); + } + public async updateIndexSettings(indexName: string, settings: string[]) { const result = await this.sendRequest({ path: `${API_BASE_PATH}/${indexName}/index_settings`, diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts index b94e75d1aedab..1315e503732e3 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts @@ -168,4 +168,42 @@ describe('deprecation logging API', () => { ).rejects.toThrow('scary error!'); }); }); + + describe('DELETE /api/upgrade_assistant/deprecation_logging/cache', () => { + it('returns ok if if the cache was deleted', async () => { + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport + .request as jest.Mock + ).mockResolvedValue({ + body: 'ok', + }); + + const resp = await routeDependencies.router.getHandler({ + method: 'delete', + pathPattern: '/api/upgrade_assistant/deprecation_logging/cache', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.status).toEqual(200); + expect( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport.request + ).toHaveBeenCalledWith({ + method: 'DELETE', + path: '/_logging/deprecation_cache', + }); + expect(resp.payload).toEqual('ok'); + }); + + it('returns an error if it throws', async () => { + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport + .request as jest.Mock + ).mockRejectedValue(new Error('scary error!')); + await expect( + routeDependencies.router.getHandler({ + method: 'delete', + pathPattern: '/api/upgrade_assistant/deprecation_logging/cache', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory) + ).rejects.toThrow('scary error!'); + }); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts index 00116ae24a3fb..5d7f0f67b0ca9 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts @@ -124,4 +124,33 @@ export function registerDeprecationLoggingRoutes({ } ) ); + + router.delete( + { + path: `${API_BASE_PATH}/deprecation_logging/cache`, + validate: false, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { client }, + }, + }, + request, + response + ) => { + try { + await client.asCurrentUser.transport.request({ + method: 'DELETE', + path: '/_logging/deprecation_cache', + }); + + return response.ok({ body: 'ok' }); + } catch (error) { + return handleEsError({ error, response }); + } + } + ) + ); } From 43fa7bdcd4467f2202ee7a69b6b50f235dbe8080 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 12 Oct 2021 12:01:51 +0100 Subject: [PATCH 54/93] [Upgrade Assistant] Add upgrade system indices section (#110593) --- .../helpers/http_requests.ts | 24 +++ .../__snapshots__/flyout.test.ts.snap | 22 ++ .../migrate_system_indices/flyout.test.ts | 42 ++++ .../migrate_system_indices.test.tsx | 136 ++++++++++++ .../overview/migrate_system_indices/mocks.ts | 58 ++++++ .../step_completion.test.ts | 86 ++++++++ .../overview/overview.helpers.ts | 22 ++ .../upgrade_assistant/common/constants.ts | 1 + .../plugins/upgrade_assistant/common/types.ts | 12 +- .../migrate_system_indices/flyout.tsx | 193 +++++++++++++++++ .../overview/migrate_system_indices/index.ts | 8 + .../migrate_system_indices.tsx | 197 ++++++++++++++++++ .../use_migrate_system_indices.ts | 95 +++++++++ .../components/overview/overview.tsx | 11 +- .../overview/upgrade_step/upgrade_step.tsx | 15 +- .../public/application/lib/api.ts | 22 +- .../server/lib/es_deprecations_status.ts | 6 +- ...ts => es_system_indices_migration.test.ts} | 6 +- ...rade.ts => es_system_indices_migration.ts} | 25 ++- .../server/routes/register_routes.ts | 2 + .../routes/system_indices_migration.test.ts | 132 ++++++++++++ .../server/routes/system_indices_migration.ts | 71 +++++++ 22 files changed, 1159 insertions(+), 27 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/__snapshots__/flyout.test.ts.snap create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/index.ts create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts rename x-pack/plugins/upgrade_assistant/server/lib/{es_system_indices_upgrade.test.ts => es_system_indices_migration.test.ts} (89%) rename x-pack/plugins/upgrade_assistant/server/lib/{es_system_indices_upgrade.ts => es_system_indices_migration.ts} (57%) create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts index 4f0e048da0792..b4ae504fb3b1a 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts @@ -158,6 +158,17 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setLoadSystemIndicesMigrationStatus = (response?: object, error?: ResponseError) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + + server.respondWith('GET', `${API_BASE_PATH}/system_indices_migration`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + const setLoadMlUpgradeModeResponse = (response?: object, error?: ResponseError) => { const status = error ? error.statusCode || 400 : 200; const body = error ? error : response; @@ -169,6 +180,17 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setSystemIndicesMigrationResponse = (response?: object, error?: ResponseError) => { + const status = error ? error.statusCode || 400 : 200; + const body = error ? error : response; + + server.respondWith('POST', `${API_BASE_PATH}/system_indices_migration`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + return { setLoadCloudBackupStatusResponse, setLoadEsDeprecationsResponse, @@ -179,6 +201,8 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { setDeleteMlSnapshotResponse, setUpgradeMlSnapshotStatusResponse, setLoadDeprecationLogsCountResponse, + setLoadSystemIndicesMigrationStatus, + setSystemIndicesMigrationResponse, setDeleteLogsCacheResponse, setStartReindexingResponse, setReindexStatusResponse, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/__snapshots__/flyout.test.ts.snap b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/__snapshots__/flyout.test.ts.snap new file mode 100644 index 0000000000000..2a512e8569d9f --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/__snapshots__/flyout.test.ts.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Overview - Migrate system indices - Flyout shows correct features in flyout table 1`] = ` +Array [ + Array [ + "Security", + "Migration failed", + ], + Array [ + "Machine Learning", + "Migration in progress", + ], + Array [ + "Kibana", + "Migration required", + ], + Array [ + "Logstash", + "Migration complete", + ], +] +`; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts new file mode 100644 index 0000000000000..1e74a966b3933 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/flyout.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; + +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; +import { setupEnvironment } from '../../helpers'; +import { systemIndicesMigrationStatus } from './mocks'; + +describe('Overview - Migrate system indices - Flyout', () => { + let testBed: OverviewTestBed; + const { server, httpRequestsMockHelpers } = setupEnvironment(); + + beforeEach(async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus(systemIndicesMigrationStatus); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + testBed.component.update(); + }); + + afterAll(() => { + server.restore(); + }); + + test('shows correct features in flyout table', async () => { + const { actions, table } = testBed; + + await actions.clickViewSystemIndicesState(); + + const { tableCellsValues } = table.getMetaData('flyoutDetails'); + + expect(tableCellsValues.length).toBe(systemIndicesMigrationStatus.features.length); + expect(tableCellsValues).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx new file mode 100644 index 0000000000000..c5f680319d0ab --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx @@ -0,0 +1,136 @@ +/* + * 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 { act } from 'react-dom/test-utils'; + +import { setupEnvironment } from '../../helpers'; +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; + +describe('Overview - Migrate system indices', () => { + let testBed: OverviewTestBed; + const { server, httpRequestsMockHelpers } = setupEnvironment(); + + beforeEach(async () => { + testBed = await setupOverviewPage(); + testBed.component.update(); + }); + + afterAll(() => { + server.restore(); + }); + + describe('Error state', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus(undefined, { + statusCode: 400, + message: 'error', + }); + + testBed = await setupOverviewPage(); + }); + + test('Is rendered', () => { + const { exists, component } = testBed; + component.update(); + + expect(exists('systemIndicesStatusErrorCallout')).toBe(true); + }); + + test('Lets the user attempt to reload migration status', async () => { + const { exists, component, actions } = testBed; + component.update(); + + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'NO_UPGRADE_NEEDED', + }); + + await actions.clickRetrySystemIndicesButton(); + + expect(exists('noMigrationNeededSection')).toBe(true); + }); + }); + + test('No migration needed', async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'NO_UPGRADE_NEEDED', + }); + + testBed = await setupOverviewPage(); + + const { exists, component } = testBed; + + component.update(); + + expect(exists('noMigrationNeededSection')).toBe(true); + expect(exists('startSystemIndicesMigrationButton')).toBe(false); + expect(exists('viewSystemIndicesStateButton')).toBe(false); + }); + + test('Migration in progress', async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'IN_PROGRESS', + }); + + testBed = await setupOverviewPage(); + + const { exists, component, find } = testBed; + + component.update(); + + // Start migration is disabled + expect(exists('startSystemIndicesMigrationButton')).toBe(true); + expect(find('startSystemIndicesMigrationButton').props().disabled).toBe(true); + // But we keep view system indices CTA + expect(exists('viewSystemIndicesStateButton')).toBe(true); + }); + + describe('Migration needed', () => { + test('Initial state', async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'UPGRADE_NEEDED', + }); + + testBed = await setupOverviewPage(); + + const { exists, component, find } = testBed; + + component.update(); + + // Start migration should be enabled + expect(exists('startSystemIndicesMigrationButton')).toBe(true); + expect(find('startSystemIndicesMigrationButton').props().disabled).toBe(false); + // Same for view system indices status + expect(exists('viewSystemIndicesStateButton')).toBe(true); + }); + + test('Handles errors when migrating', async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'UPGRADE_NEEDED', + }); + httpRequestsMockHelpers.setSystemIndicesMigrationResponse(undefined, { + statusCode: 400, + message: 'error', + }); + + testBed = await setupOverviewPage(); + + const { exists, component, find } = testBed; + + await act(async () => { + find('startSystemIndicesMigrationButton').simulate('click'); + }); + + component.update(); + + // Error is displayed + expect(exists('startSystemIndicesMigrationCalloutError')).toBe(true); + // CTA is enabled + expect(exists('startSystemIndicesMigrationButton')).toBe(true); + expect(find('startSystemIndicesMigrationButton').props().disabled).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts new file mode 100644 index 0000000000000..298f537819507 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SystemIndicesMigrationStatus } from '../../../../common/types'; + +export const systemIndicesMigrationStatus: SystemIndicesMigrationStatus = { + upgrade_status: 'UPGRADE_NEEDED', + features: [ + { + feature_name: 'security', + minimum_index_version: '7.1.1', + upgrade_status: 'ERROR', + indices: [ + { + index: '.security-7', + version: '7.1.1', + }, + ], + }, + { + feature_name: 'machine_learning', + minimum_index_version: '7.1.2', + upgrade_status: 'IN_PROGRESS', + indices: [ + { + index: '.ml-config', + version: '7.1.2', + }, + ], + }, + { + feature_name: 'kibana', + minimum_index_version: '7.1.3', + upgrade_status: 'UPGRADE_NEEDED', + indices: [ + { + index: '.kibana', + version: '7.1.3', + }, + ], + }, + { + feature_name: 'logstash', + minimum_index_version: '7.1.4', + upgrade_status: 'NO_UPGRADE_NEEDED', + indices: [ + { + index: '.logstash-config', + version: '7.1.4', + }, + ], + }, + ], +}; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts new file mode 100644 index 0000000000000..c5173481d8dac --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; + +import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; +import { setupEnvironment, advanceTime } from '../../helpers'; +import { SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS } from '../../../../common/constants'; + +describe('Overview - Migrate system indices - Step completion', () => { + let testBed: OverviewTestBed; + const { server, httpRequestsMockHelpers } = setupEnvironment(); + + afterAll(() => { + server.restore(); + }); + + test(`It's complete when no upgrade is needed`, async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'NO_UPGRADE_NEEDED', + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, component } = testBed; + + component.update(); + + expect(exists(`migrateSystemIndicesStep-complete`)).toBe(true); + }); + + test(`It's incomplete when migration is needed`, async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'UPGRADE_NEEDED', + }); + + await act(async () => { + testBed = await setupOverviewPage(); + }); + + const { exists, component } = testBed; + + component.update(); + + expect(exists(`migrateSystemIndicesStep-incomplete`)).toBe(true); + }); + + describe('Poll for new status', () => { + beforeEach(async () => { + jest.useFakeTimers(); + + // First request should make the step be incomplete + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'IN_PROGRESS', + }); + + testBed = await setupOverviewPage(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + test('renders step as complete when a upgraded needed status is followed by a no upgrade needed', async () => { + const { exists } = testBed; + + expect(exists('migrateSystemIndicesStep-incomplete')).toBe(true); + + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + upgrade_status: 'NO_UPGRADE_NEEDED', + }); + + // Resolve the polling timeout. + await advanceTime(SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS); + testBed.component.update(); + + expect(exists('migrateSystemIndicesStep-complete')).toBe(true); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts index 1457af010af5b..242d6893d1518 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.helpers.ts @@ -57,10 +57,32 @@ const createActions = (testBed: TestBed) => { component.update(); }; + const clickViewSystemIndicesState = async () => { + const { find, component } = testBed; + + await act(async () => { + find('viewSystemIndicesStateButton').simulate('click'); + }); + + component.update(); + }; + + const clickRetrySystemIndicesButton = async () => { + const { find, component } = testBed; + + await act(async () => { + find('systemIndicesStatusRetryButton').simulate('click'); + }); + + component.update(); + }; + return { clickDeprecationToggle, clickRetryButton, clickResetButton, + clickViewSystemIndicesState, + clickRetrySystemIndicesButton, }; }; diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index c037e2407ab04..db8e2a707baa8 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -36,3 +36,4 @@ export const DEPRECATION_LOGS_INDEX_PATTERN = '.logs-deprecation.elasticsearch-d export const CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS = 60000; export const DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS = 15000; +export const SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS = 15000; diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index f955aa05288e3..1189cfd1866c4 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -251,8 +251,8 @@ export interface DeprecationLoggingStatus { isDeprecationLoggingEnabled: boolean; } -export type UPGRADE_STATUS = 'UPGRADE_NEEDED' | 'NO_UPGRADE_NEEDED' | 'IN_PROGRESS'; -export interface SystemIndicesUpgradeFeature { +export type UPGRADE_STATUS = 'UPGRADE_NEEDED' | 'NO_UPGRADE_NEEDED' | 'IN_PROGRESS' | 'ERROR'; +export interface SystemIndicesMigrationFeature { id?: string; feature_name: string; minimum_index_version: string; @@ -262,7 +262,11 @@ export interface SystemIndicesUpgradeFeature { version: string; }>; } -export interface SystemIndicesUpgradeStatus { - features: SystemIndicesUpgradeFeature[]; +export interface SystemIndicesMigrationStatus { + features: SystemIndicesMigrationFeature[]; upgrade_status: UPGRADE_STATUS; } +export interface SystemIndicesMigrationStarted { + features: SystemIndicesMigrationFeature[]; + accepted: boolean; +} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx new file mode 100644 index 0000000000000..612fcdc2e4c03 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx @@ -0,0 +1,193 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { startCase } from 'lodash'; +import { i18n } from '@kbn/i18n'; + +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiLoadingSpinner, + EuiTitle, + EuiText, + EuiIcon, + EuiSpacer, + EuiInMemoryTable, +} from '@elastic/eui'; + +import { + SystemIndicesMigrationStatus, + SystemIndicesMigrationFeature, + UPGRADE_STATUS, +} from '../../../../../common/types'; + +export interface SystemIndicesFlyoutProps { + closeFlyout: () => void; + data: SystemIndicesMigrationStatus; + nextMajor: number; +} + +const i18nTexts = { + closeButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.flyoutCloseButtonLabel', + { + defaultMessage: 'Close', + } + ), + flyoutTitle: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.flyoutTitle', { + defaultMessage: 'Migrate system indices', + }), + flyoutDescription: (nextMajor: number) => + i18n.translate('xpack.upgradeAssistant.overview.systemIndices.flyoutDescription', { + defaultMessage: + 'Migrate the indices that store information for the following features before you upgrade to {nextMajor}.0.', + values: { nextMajor }, + }), + migrationCompleteLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.migrationCompleteLabel', + { + defaultMessage: 'Migration complete', + } + ), + needsMigrationLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.needsMigrationLabel', + { + defaultMessage: 'Migration required', + } + ), + migratingLabel: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.migratingLabel', { + defaultMessage: 'Migration in progress', + }), + errorLabel: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.errorLabel', { + defaultMessage: 'Migration failed', + }), + featureNameTableColumn: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.featureNameTableColumn', + { + defaultMessage: 'Feature', + } + ), + statusTableColumn: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.statusTableColumn', + { + defaultMessage: 'Status', + } + ), +}; + +const renderMigrationStatus = (status: UPGRADE_STATUS) => { + if (status === 'NO_UPGRADE_NEEDED') { + return ( + + + + + + +

{i18nTexts.migrationCompleteLabel}

+
+
+
+ ); + } + + if (status === 'UPGRADE_NEEDED') { + return ( + +

{i18nTexts.needsMigrationLabel}

+
+ ); + } + + if (status === 'IN_PROGRESS') { + return ( + + + + + + +

{i18nTexts.migratingLabel}

+
+
+
+ ); + } + + if (status === 'ERROR') { + return ( + + + + + + +

{i18nTexts.errorLabel}

+
+
+
+ ); + } + + return ''; +}; + +const columns = [ + { + field: 'feature_name', + name: i18nTexts.featureNameTableColumn, + sortable: true, + truncateText: true, + render: (name: string) => startCase(name), + }, + { + field: 'upgrade_status', + name: i18nTexts.statusTableColumn, + sortable: true, + render: renderMigrationStatus, + }, +]; + +export const SystemIndicesFlyout = ({ closeFlyout, data, nextMajor }: SystemIndicesFlyoutProps) => { + return ( + <> + + +

{i18nTexts.flyoutTitle}

+
+
+ + +

{i18nTexts.flyoutDescription(nextMajor)}

+
+ + + data-test-subj="featuresTable" + itemId="feature_name" + items={data.features} + columns={columns} + pagination={true} + sorting={true} + /> +
+ + + + + {i18nTexts.closeButtonLabel} + + + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/index.ts new file mode 100644 index 0000000000000..0be86929f2a43 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { getMigrateSystemIndicesStep } from './migrate_system_indices'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx new file mode 100644 index 0000000000000..ab370c99bfc58 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx @@ -0,0 +1,197 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useEffect } from 'react'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiText, + EuiButton, + EuiSpacer, + EuiIcon, + EuiButtonEmpty, + EuiCallOut, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; +import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; + +import type { OverviewStepProps } from '../../types'; +import { useMigrateSystemIndices } from './use_migrate_system_indices'; + +interface Props { + setIsComplete: OverviewStepProps['setIsComplete']; +} + +interface StepProps extends OverviewStepProps { + nextMajor: number; +} + +const i18nTexts = { + title: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.title', { + defaultMessage: 'Migrate system indices', + }), + bodyDescription: (nextMajor: number) => ( + + ), + startButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.startButtonLabel', + { + defaultMessage: 'Migrate indices', + } + ), + inProgressButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.inProgressButtonLabel', + { + defaultMessage: 'Migration in progress', + } + ), + noMigrationNeeded: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.noMigrationNeeded', + { + defaultMessage: 'Migration complete', + } + ), + viewSystemIndicesStatus: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.viewSystemIndicesStatus', + { + defaultMessage: 'View migration information', + } + ), + retryButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.retryButtonLabel', + { + defaultMessage: 'Retry migration', + } + ), + loadingError: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.loadingError', { + defaultMessage: 'Could not retrieve the system indices status', + }), +}; + +const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) => { + const { beginSystemIndicesMigration, startMigrationStatus, migrationStatus, setShowFlyout } = + useMigrateSystemIndices(); + + useEffect(() => { + setIsComplete(migrationStatus.data?.upgrade_status === 'NO_UPGRADE_NEEDED'); + // Depending upon setIsComplete would create an infinite loop. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [migrationStatus.data?.upgrade_status]); + + if (migrationStatus.error) { + return ( + +

+ {migrationStatus.error.statusCode} - {migrationStatus.error.message} +

+ + {i18nTexts.retryButtonLabel} + +
+ ); + } + + if (migrationStatus.data?.upgrade_status === 'NO_UPGRADE_NEEDED') { + return ( + + + + + + +

{i18nTexts.noMigrationNeeded}

+
+
+
+ ); + } + + const isButtonDisabled = migrationStatus.isInitialRequest && migrationStatus.isLoading; + const isMigrating = migrationStatus.data?.upgrade_status === 'IN_PROGRESS'; + + return ( + <> + {startMigrationStatus.statusType === 'error' && ( + <> + + + + )} + + + + + {isMigrating ? i18nTexts.inProgressButtonLabel : i18nTexts.startButtonLabel} + + + + setShowFlyout(true)} + isDisabled={isButtonDisabled} + data-test-subj="viewSystemIndicesStateButton" + > + {i18nTexts.viewSystemIndicesStatus} + + + + + ); +}; + +export const getMigrateSystemIndicesStep = ({ + nextMajor, + isComplete, + setIsComplete, +}: StepProps): EuiStepProps => { + const status = isComplete ? 'complete' : 'incomplete'; + + return { + title: i18nTexts.title, + status, + 'data-test-subj': `migrateSystemIndicesStep-${status}`, + children: ( + <> + +

{i18nTexts.bodyDescription(nextMajor)}

+
+ + + + + + ), + }; +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts new file mode 100644 index 0000000000000..d6e9bd2a9d5ff --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback, useState, useEffect } from 'react'; +import useInterval from 'react-use/lib/useInterval'; + +import { SystemIndicesFlyout, SystemIndicesFlyoutProps } from './flyout'; +import { useAppContext } from '../../../app_context'; +import type { ResponseError } from '../../../lib/api'; +import { GlobalFlyout } from '../../../../shared_imports'; +import { SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS } from '../../../../../common/constants'; + +const FLYOUT_ID = 'migrateSystemIndicesFlyout'; +const { useGlobalFlyout } = GlobalFlyout; + +export type StatusType = 'idle' | 'error' | 'started'; +interface MigrationStatus { + statusType: StatusType; + error?: ResponseError; +} + +export const useMigrateSystemIndices = () => { + const { + services: { api }, + kibanaVersionInfo: { nextMajor }, + } = useAppContext(); + + const [showFlyout, setShowFlyout] = useState(false); + + const [startMigrationStatus, setStartMigrationStatus] = useState({ + statusType: 'idle', + }); + + const { data, error, isLoading, resendRequest, isInitialRequest } = + api.useLoadSystemIndicesMigrationStatus(); + const isInProgress = data?.upgrade_status === 'IN_PROGRESS'; + + // We only want to poll for the status while the migration process is in progress. + useInterval(resendRequest, isInProgress ? SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS : null); + + const { addContent: addContentToGlobalFlyout, removeContent: removeContentFromGlobalFlyout } = + useGlobalFlyout(); + + const closeFlyout = useCallback(() => { + setShowFlyout(false); + removeContentFromGlobalFlyout(FLYOUT_ID); + }, [removeContentFromGlobalFlyout]); + + useEffect(() => { + if (showFlyout) { + addContentToGlobalFlyout({ + id: FLYOUT_ID, + Component: SystemIndicesFlyout, + props: { + data: data!, + nextMajor, + closeFlyout, + }, + flyoutProps: { + onClose: closeFlyout, + }, + }); + } + }, [addContentToGlobalFlyout, data, showFlyout, closeFlyout, nextMajor]); + + const beginSystemIndicesMigration = useCallback(async () => { + const { error: startMigrationError } = await api.migrateSystemIndices(); + + setStartMigrationStatus({ + statusType: startMigrationError ? 'error' : 'started', + error: startMigrationError ?? undefined, + }); + + if (!startMigrationError) { + resendRequest(); + } + }, [api, resendRequest]); + + return { + setShowFlyout, + startMigrationStatus, + beginSystemIndicesMigration, + migrationStatus: { + data, + error, + isLoading, + resendRequest, + isInitialRequest, + }, + }; +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index 32e9c78f6d6ac..e382e3288bc68 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -25,8 +25,9 @@ import { getBackupStep } from './backup_step'; import { getFixIssuesStep } from './fix_issues_step'; import { getFixLogsStep } from './fix_logs_step'; import { getUpgradeStep } from './upgrade_step'; +import { getMigrateSystemIndicesStep } from './migrate_system_indices'; -type OverviewStep = 'backup' | 'fix_issues' | 'fix_logs'; +type OverviewStep = 'backup' | 'migrate_system_indices' | 'fix_issues' | 'fix_logs'; export const Overview: FunctionComponent = () => { const { @@ -55,6 +56,7 @@ export const Overview: FunctionComponent = () => { const [completedStepsMap, setCompletedStepsMap] = useState({ backup: false, + migrate_system_indices: false, fix_issues: false, fix_logs: false, }); @@ -112,6 +114,11 @@ export const Overview: FunctionComponent = () => { isComplete: isStepComplete('backup'), setIsComplete: setCompletedStep.bind(null, 'backup'), }), + getMigrateSystemIndicesStep({ + nextMajor, + isComplete: isStepComplete('migrate_system_indices'), + setIsComplete: setCompletedStep.bind(null, 'migrate_system_indices'), + }), getFixIssuesStep({ nextMajor, isComplete: isStepComplete('fix_issues'), @@ -121,7 +128,7 @@ export const Overview: FunctionComponent = () => { isComplete: isStepComplete('fix_logs'), setIsComplete: setCompletedStep.bind(null, 'fix_logs'), }), - getUpgradeStep({ docLinks, nextMajor }), + getUpgradeStep({ nextMajor }), ]} /> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx index 5acbf280e0b4e..4af4a345be89d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx @@ -17,7 +17,6 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; -import type { DocLinksStart } from 'src/core/public'; import { useAppContext } from '../../../app_context'; const i18nTexts = { @@ -48,9 +47,12 @@ const i18nTexts = { }), }; -const UpgradeStep = ({ docLinks }: { docLinks: DocLinksStart }) => { +const UpgradeStep = () => { const { plugins: { cloud }, + services: { + core: { docLinks }, + }, } = useAppContext(); const isCloudEnabled: boolean = Boolean(cloud?.isCloudEnabled); let callToAction; @@ -115,16 +117,11 @@ const UpgradeStep = ({ docLinks }: { docLinks: DocLinksStart }) => { ); }; -interface Props { - docLinks: DocLinksStart; - nextMajor: number; -} - -export const getUpgradeStep = ({ docLinks, nextMajor }: Props): EuiStepProps => { +export const getUpgradeStep = ({ nextMajor }: { nextMajor: number }): EuiStepProps => { return { title: i18nTexts.upgradeStepTitle(nextMajor), status: 'incomplete', 'data-test-subj': 'upgradeStep', - children: , + children: , }; }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index b701a5a5eff2c..24a45fa1018fe 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -7,7 +7,11 @@ import { HttpSetup } from 'src/core/public'; -import { ESUpgradeStatus, CloudBackupStatus } from '../../../common/types'; +import { + ESUpgradeStatus, + CloudBackupStatus, + SystemIndicesMigrationStatus, +} from '../../../common/types'; import { API_BASE_PATH, DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS, @@ -58,6 +62,22 @@ export class ApiService { }); } + public useLoadSystemIndicesMigrationStatus() { + return this.useRequest({ + path: `${API_BASE_PATH}/system_indices_migration`, + method: 'get', + }); + } + + public async migrateSystemIndices() { + const result = await this.sendRequest({ + path: `${API_BASE_PATH}/system_indices_migration`, + method: 'post', + }); + + return result; + } + public useLoadEsDeprecations() { return this.useRequest({ path: `${API_BASE_PATH}/es_deprecations`, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts index 401967d678a35..2e2c80b790cd5 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts @@ -12,9 +12,9 @@ import { EnrichedDeprecationInfo, ESUpgradeStatus } from '../../common/types'; import { esIndicesStateCheck } from './es_indices_state_check'; import { - getESSystemIndicesUpgradeStatus, + getESSystemIndicesMigrationStatus, convertFeaturesToIndicesArray, -} from '../lib/es_system_indices_upgrade'; +} from '../lib/es_system_indices_migration'; export async function getESUpgradeStatus( dataClient: IScopedClusterClient @@ -23,7 +23,7 @@ export async function getESUpgradeStatus( const getCombinedDeprecations = async () => { const indices = await getCombinedIndexInfos(deprecations, dataClient); - const systemIndices = await getESSystemIndicesUpgradeStatus(dataClient.asCurrentUser); + const systemIndices = await getESSystemIndicesMigrationStatus(dataClient.asCurrentUser); const systemIndicesList = convertFeaturesToIndicesArray(systemIndices.features); return Object.keys(deprecations).reduce((combinedDeprecations, deprecationType) => { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.test.ts similarity index 89% rename from x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.test.ts index a4a6e1053702c..6f4ca5a341218 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.test.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { convertFeaturesToIndicesArray } from './es_system_indices_upgrade'; -import { SystemIndicesUpgradeStatus } from '../../common/types'; +import { convertFeaturesToIndicesArray } from './es_system_indices_migration'; +import { SystemIndicesMigrationStatus } from '../../common/types'; -const esUpgradeSystemIndicesStatusMock: SystemIndicesUpgradeStatus = { +const esUpgradeSystemIndicesStatusMock: SystemIndicesMigrationStatus = { features: [ { feature_name: 'machine_learning', diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.ts similarity index 57% rename from x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.ts index 32cea54a884e3..aa239de7dd008 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_upgrade.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.ts @@ -7,10 +7,14 @@ import { flow, flatMap, map, flatten, uniq } from 'lodash/fp'; import { ElasticsearchClient } from 'src/core/server'; -import { SystemIndicesUpgradeStatus, SystemIndicesUpgradeFeature } from '../../common/types'; +import { + SystemIndicesMigrationStatus, + SystemIndicesMigrationFeature, + SystemIndicesMigrationStarted, +} from '../../common/types'; export const convertFeaturesToIndicesArray = ( - features: SystemIndicesUpgradeFeature[] + features: SystemIndicesMigrationFeature[] ): string[] => { return flow( // Map each feature into Indices[] @@ -24,13 +28,24 @@ export const convertFeaturesToIndicesArray = ( )(features); }; -export const getESSystemIndicesUpgradeStatus = async ( +export const getESSystemIndicesMigrationStatus = async ( client: ElasticsearchClient -): Promise => { +): Promise => { const { body } = await client.transport.request({ method: 'GET', path: '/_migration/system_features', }); - return body as SystemIndicesUpgradeStatus; + return body as SystemIndicesMigrationStatus; +}; + +export const startESSystemIndicesMigration = async ( + client: ElasticsearchClient +): Promise => { + const { body } = await client.transport.request({ + method: 'POST', + path: '/_migration/system_features', + }); + + return body as SystemIndicesMigrationStarted; }; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index cc4be54042583..ec02e814b2a8d 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -9,6 +9,7 @@ import { RouteDependencies } from '../types'; import { registerAppRoutes } from './app'; import { registerCloudBackupStatusRoutes } from './cloud_backup_status'; +import { registerSystemIndicesMigrationRoutes } from './system_indices_migration'; import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; import { registerReindexIndicesRoutes, registerBatchReindexIndicesRoutes } from './reindex_indices'; @@ -21,6 +22,7 @@ import { registerUpgradeStatusRoute } from './status'; export function registerRoutes(dependencies: RouteDependencies, getWorker: () => ReindexWorker) { registerAppRoutes(dependencies); registerCloudBackupStatusRoutes(dependencies); + registerSystemIndicesMigrationRoutes(dependencies); registerESDeprecationRoutes(dependencies); registerDeprecationLoggingRoutes(dependencies); registerReindexIndicesRoutes(dependencies, getWorker); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts new file mode 100644 index 0000000000000..2d15bed7e29e3 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts @@ -0,0 +1,132 @@ +/* + * 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 { kibanaResponseFactory } from 'src/core/server'; +import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; +import { createRequestMock } from './__mocks__/request.mock'; +import { handleEsError } from '../shared_imports'; + +jest.mock('../lib/es_version_precheck', () => ({ + versionCheckHandlerWrapper: (a: any) => a, +})); + +import { registerSystemIndicesMigrationRoutes } from './system_indices_migration'; + +const mockedResponse = { + features: [ + { + feature_name: 'security', + minimum_index_version: '7.1.1', + upgrade_status: 'NO_UPGRADE_NEEDED', + indices: [ + { + index: '.security-7', + version: '7.1.1', + }, + ], + }, + ], + upgrade_status: 'UPGRADE_NEEDED', +}; + +/** + * Since these route callbacks are so thin, these serve simply as integration tests + * to ensure they're wired up to the lib functions correctly. + */ +describe('Migrate system indices API', () => { + let mockRouter: MockRouter; + let routeDependencies: any; + + beforeEach(() => { + mockRouter = createMockRouter(); + routeDependencies = { + router: mockRouter, + lib: { handleEsError }, + }; + registerSystemIndicesMigrationRoutes(routeDependencies); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + describe('GET /api/upgrade_assistant/system_indices_migration', () => { + it('returns system indices migration status', async () => { + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport + .request as jest.Mock + ).mockResolvedValue({ + body: mockedResponse, + }); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/system_indices_migration', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.status).toEqual(200); + expect( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport.request + ).toHaveBeenCalledWith({ + method: 'GET', + path: '/_migration/system_features', + }); + expect(resp.payload).toEqual(mockedResponse); + }); + + it('returns an error if it throws', async () => { + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport + .request as jest.Mock + ).mockRejectedValue(new Error('scary error!')); + await expect( + routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/system_indices_migration', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory) + ).rejects.toThrow('scary error!'); + }); + }); + + describe('POST /api/upgrade_assistant/system_indices_migration', () => { + it('returns system indices migration status', async () => { + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport + .request as jest.Mock + ).mockResolvedValue({ + body: mockedResponse, + }); + + const resp = await routeDependencies.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/system_indices_migration', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + + expect(resp.status).toEqual(200); + expect( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport.request + ).toHaveBeenCalledWith({ + method: 'POST', + path: '/_migration/system_features', + }); + expect(resp.payload).toEqual(mockedResponse); + }); + + it('returns an error if it throws', async () => { + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.transport + .request as jest.Mock + ).mockRejectedValue(new Error('scary error!')); + await expect( + routeDependencies.router.getHandler({ + method: 'post', + pathPattern: '/api/upgrade_assistant/system_indices_migration', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory) + ).rejects.toThrow('scary error!'); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts new file mode 100644 index 0000000000000..dbb0cca7502bb --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { API_BASE_PATH } from '../../common/constants'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { RouteDependencies } from '../types'; +import { + getESSystemIndicesMigrationStatus, + startESSystemIndicesMigration, +} from '../lib/es_system_indices_migration'; + +export function registerSystemIndicesMigrationRoutes({ + router, + lib: { handleEsError }, +}: RouteDependencies) { + // GET status of the system indices migration + router.get( + { path: `${API_BASE_PATH}/system_indices_migration`, validate: false }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { client }, + }, + }, + request, + response + ) => { + try { + const status = await getESSystemIndicesMigrationStatus(client.asCurrentUser); + + return response.ok({ + body: status, + }); + } catch (error) { + return handleEsError({ error, response }); + } + } + ) + ); + + // POST starts the system indices migration + router.post( + { path: `${API_BASE_PATH}/system_indices_migration`, validate: false }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { client }, + }, + }, + request, + response + ) => { + try { + const status = await startESSystemIndicesMigration(client.asCurrentUser); + + return response.ok({ + body: status, + }); + } catch (error) { + return handleEsError({ error, response }); + } + } + ) + ); +} From 90cbcdf1d34621ae66cddb101375d66b0672a277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 12 Oct 2021 13:50:36 +0200 Subject: [PATCH 55/93] [Upgrade Assistant] Reindexing progress (#114275) * [Upgrade Assistant] Added reindexing progress in % to the reindex flyout and es deprecations table * [Upgrade Assistant] Renamed first argument in `getReindexProgressLabel` to `reindexTaskPercComplete` for consistency Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../reindex_deprecation_flyout.test.ts | 107 +++++++++++++++ .../checklist_step.test.tsx.snap | 11 -- .../reindex/flyout/checklist_step.tsx | 9 -- .../reindex/flyout/progress.test.tsx | 125 +++++++++--------- .../reindex/flyout/progress.tsx | 98 ++++++++------ .../reindex/resolution_table_cell.tsx | 9 +- .../reindex/use_reindex_state.tsx | 4 +- .../public/application/lib/utils.test.ts | 33 ++++- .../public/application/lib/utils.ts | 48 +++++++ 9 files changed, 321 insertions(+), 123 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts index ca9253c1140b0..3c6fe0e5f5329 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts @@ -10,6 +10,7 @@ import { act } from 'react-dom/test-utils'; import { setupEnvironment } from '../helpers'; import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './mocked_responses'; +import { ReindexStatus, ReindexStep } from '../../../common/types'; // Note: The reindexing flyout UX is subject to change; more tests should be added here once functionality is built out describe('Reindex deprecation flyout', () => { @@ -93,4 +94,110 @@ describe('Reindex deprecation flyout', () => { expect(exists('reindexDetails.fetchFailedCallout')).toBe(true); }); + + describe('reindexing progress', () => { + it('has not started yet', async () => { + const { actions, find, exists } = testBed; + + await actions.table.clickDeprecationRowAt('reindex', 0); + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing process'); + expect(exists('cancelReindexingDocumentsButton')).toBe(false); + }); + + it('has started but not yet reindexing documents', async () => { + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: { + status: ReindexStatus.inProgress, + lastCompletedStep: ReindexStep.readonly, + reindexTaskPercComplete: null, + }, + warnings: [], + hasRequiredPrivileges: true, + }); + + await act(async () => { + testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); + }); + + testBed.component.update(); + const { actions, find, exists } = testBed; + + await actions.table.clickDeprecationRowAt('reindex', 0); + + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 5%'); + expect(exists('cancelReindexingDocumentsButton')).toBe(false); + }); + + it('has started reindexing documents', async () => { + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: { + status: ReindexStatus.inProgress, + lastCompletedStep: ReindexStep.reindexStarted, + reindexTaskPercComplete: 0.25, + }, + warnings: [], + hasRequiredPrivileges: true, + }); + + await act(async () => { + testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); + }); + + testBed.component.update(); + const { actions, find, exists } = testBed; + + await actions.table.clickDeprecationRowAt('reindex', 0); + + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 31%'); + expect(exists('cancelReindexingDocumentsButton')).toBe(true); + }); + + it('has completed reindexing documents', async () => { + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: { + status: ReindexStatus.inProgress, + lastCompletedStep: ReindexStep.reindexCompleted, + reindexTaskPercComplete: 1, + }, + warnings: [], + hasRequiredPrivileges: true, + }); + + await act(async () => { + testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); + }); + + testBed.component.update(); + const { actions, find, exists } = testBed; + + await actions.table.clickDeprecationRowAt('reindex', 0); + + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 95%'); + expect(exists('cancelReindexingDocumentsButton')).toBe(false); + }); + + it('has completed', async () => { + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: { + status: ReindexStatus.completed, + lastCompletedStep: ReindexStep.aliasCreated, + reindexTaskPercComplete: 1, + }, + warnings: [], + hasRequiredPrivileges: true, + }); + + await act(async () => { + testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); + }); + + testBed.component.update(); + const { actions, find, exists } = testBed; + + await actions.table.clickDeprecationRowAt('reindex', 0); + + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing process'); + expect(exists('cancelReindexingDocumentsButton')).toBe(false); + }); + }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index 26119c2b62040..be84bbf143ab3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -30,17 +30,6 @@ exports[`ChecklistFlyout renders 1`] = `

- -

- -

-
- -

- -

-
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx index c58230b3563f3..ad1c7d8e94105 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx @@ -29,45 +29,69 @@ describe('ReindexProgress', () => { ); expect(wrapper).toMatchInlineSnapshot(` -, - }, - Object { - "status": "incomplete", - "title": , - }, - Object { - "status": "incomplete", - "title": , - }, - Object { - "status": "incomplete", - "title": , - }, - ] - } -/> -`); + + +

+ +

+
+ , + }, + Object { + "status": "incomplete", + "title": , + }, + Object { + "status": "incomplete", + "title": + + + + , + }, + Object { + "status": "incomplete", + "title": , + }, + ] + } + /> +
+ `); }); it('displays errors in the step that failed', () => { @@ -84,30 +108,9 @@ describe('ReindexProgress', () => { cancelReindex={jest.fn()} /> ); - - const aliasStep = wrapper.props().steps[3]; + const aliasStep = (wrapper.find('StepProgress').props() as any).steps[3]; expect(aliasStep.children.props.errorMessage).toEqual( `This is an error that happened on alias switch` ); }); - - it('shows reindexing document progress bar', () => { - const wrapper = shallow( - - ); - - const reindexStep = wrapper.props().steps[2]; - expect(reindexStep.children.type.name).toEqual('ReindexProgressBar'); - expect(reindexStep.children.props.reindexState.reindexTaskPercComplete).toEqual(0.25); - }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx index 7a2c9943691a3..afeac303284f1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx @@ -12,8 +12,8 @@ import { EuiCallOut, EuiFlexGroup, EuiFlexItem, - EuiProgress, EuiText, + EuiTitle, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -21,6 +21,7 @@ import { ReindexStatus, ReindexStep } from '../../../../../../../common/types'; import { LoadingState } from '../../../../types'; import type { ReindexState } from '../use_reindex_state'; import { StepProgress, StepProgressStep } from './step_progress'; +import { getReindexProgressLabel } from '../../../../../lib/utils'; const ErrorCallout: React.FunctionComponent<{ errorMessage: string | null }> = ({ errorMessage, @@ -39,19 +40,10 @@ const PausedCallout = () => ( /> ); -const ReindexProgressBar: React.FunctionComponent<{ +const CancelReindexingDocumentsButton: React.FunctionComponent<{ reindexState: ReindexState; cancelReindex: () => void; -}> = ({ - reindexState: { lastCompletedStep, status, reindexTaskPercComplete, cancelLoadingState }, - cancelReindex, -}) => { - const progressBar = reindexTaskPercComplete ? ( - - ) : ( - - ); - +}> = ({ reindexState: { lastCompletedStep, status, cancelLoadingState }, cancelReindex }) => { let cancelText: React.ReactNode; switch (cancelLoadingState) { case LoadingState.Loading: @@ -71,7 +63,6 @@ const ReindexProgressBar: React.FunctionComponent<{ ); break; case LoadingState.Error: - cancelText = 'Could not cancel'; cancelText = ( - {progressBar} - - - {cancelText} - - -
+ + {cancelText} + ); }; @@ -118,7 +105,12 @@ export const ReindexProgress: React.FunctionComponent<{ reindexState: ReindexState; cancelReindex: () => void; }> = (props) => { - const { errorMessage, lastCompletedStep = -1, status } = props.reindexState; + const { + errorMessage, + lastCompletedStep = -1, + status, + reindexTaskPercComplete, + } = props.reindexState; const stepDetails = (thisStep: ReindexStep): Pick => { const previousStep = orderedSteps[orderedSteps.indexOf(thisStep) - 1]; @@ -151,14 +143,23 @@ export const ReindexProgress: React.FunctionComponent<{ } }; - // The reindexing step is special because it combines the starting and complete statuses into a single UI - // with a progress bar. + // The reindexing step is special because it generally lasts longer and can be cancelled mid-flight const reindexingDocsStep = { title: ( - + + + + + {(lastCompletedStep === ReindexStep.newIndexCreated || + lastCompletedStep === ReindexStep.reindexStarted) && ( + + + + )} + ), } as StepProgressStep; @@ -189,7 +190,6 @@ export const ReindexProgress: React.FunctionComponent<{ lastCompletedStep === ReindexStep.reindexStarted ) { reindexingDocsStep.status = 'inProgress'; - reindexingDocsStep.children = ; } else { reindexingDocsStep.status = 'complete'; } @@ -225,5 +225,27 @@ export const ReindexProgress: React.FunctionComponent<{ }, ]; - return ; + return ( + <> + +

+ {status === ReindexStatus.inProgress ? ( + + ) : ( + + )} +

+
+ + + ); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx index ff2f01befb180..84c6c16d4032a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx @@ -17,6 +17,7 @@ import { EuiToolTip, } from '@elastic/eui'; import { ReindexStatus } from '../../../../../../common/types'; +import { getReindexProgressLabel } from '../../../../lib/utils'; import { LoadingState } from '../../../types'; import { useReindexContext } from './context'; @@ -99,7 +100,13 @@ export const ReindexResolutionCell: React.FunctionComponent = () => { - {i18nTexts.reindexInProgressText} + + {i18nTexts.reindexInProgressText}{' '} + {getReindexProgressLabel( + reindexState.reindexTaskPercComplete, + reindexState.lastCompletedStep + )} +
); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index 32a6c75ff6eec..cbeebd00f2bb8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -127,7 +127,7 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A api.sendReindexTelemetryData({ start: true }); - const { data, error } = await api.startReindexTask(indexName); + const { data: reindexOp, error } = await api.startReindexTask(indexName); if (error) { setReindexState({ @@ -139,7 +139,7 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A return; } - setReindexState(getReindexState(reindexState, data)); + setReindexState(getReindexState(reindexState, { reindexOp })); updateStatus(); }, [api, indexName, reindexState, updateStatus]); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts index 83fc9cabbbecc..37392c832ecf5 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts @@ -6,7 +6,8 @@ */ import { DEPRECATION_WARNING_UPPER_LIMIT } from '../../../common/constants'; -import { validateRegExpString, getDeprecationsUpperLimit } from './utils'; +import { getDeprecationsUpperLimit, getReindexProgressLabel, validateRegExpString } from './utils'; +import { ReindexStep } from '../../../common/types'; describe('validRegExpString', () => { it('correctly returns false for invalid strings', () => { @@ -35,3 +36,33 @@ describe('getDeprecationsUpperLimit', () => { ); }); }); + +describe('getReindexProgressLabel', () => { + it('returns 0% when the reindex task has just been created', () => { + expect(getReindexProgressLabel(null, ReindexStep.created)).toBe('0%'); + }); + + it('returns 5% when the index has been made read-only', () => { + expect(getReindexProgressLabel(null, ReindexStep.readonly)).toBe('5%'); + }); + + it('returns 10% when the reindexing documents has started, but the progress is null', () => { + expect(getReindexProgressLabel(null, ReindexStep.reindexStarted)).toBe('10%'); + }); + + it('returns 10% when the reindexing documents has started, but the progress is 0', () => { + expect(getReindexProgressLabel(0, ReindexStep.reindexStarted)).toBe('10%'); + }); + + it('returns 53% when the reindexing documents progress is 0.5', () => { + expect(getReindexProgressLabel(0.5, ReindexStep.reindexStarted)).toBe('53%'); + }); + + it('returns 95% when the reindexing documents progress is 1', () => { + expect(getReindexProgressLabel(1, ReindexStep.reindexStarted)).toBe('95%'); + }); + + it('returns 100% when alias has been switched', () => { + expect(getReindexProgressLabel(null, ReindexStep.aliasCreated)).toBe('100%'); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts index b90038e1166ab..bdbc0949e368b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts @@ -9,6 +9,7 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { tryCatch, fold } from 'fp-ts/lib/Either'; import { DEPRECATION_WARNING_UPPER_LIMIT } from '../../../common/constants'; +import { ReindexStep } from '../../../common/types'; export const validateRegExpString = (s: string) => pipe( @@ -34,3 +35,50 @@ export const getDeprecationsUpperLimit = (count: number) => { return count.toString(); }; + +/* + * Reindexing task consists of 4 steps: making the index read-only, creating a new index, + * reindexing documents into the new index and switching alias from the old to the new index. + * Steps 1, 2 and 4 each contribute 5% to the overall progress. + * Step 3 (reindexing documents) can take a long time for large indices and its progress is calculated + * between 10% and 95% of the overall progress depending on its completeness percentage. + */ +export const getReindexProgressLabel = ( + reindexTaskPercComplete: number | null, + lastCompletedStep: ReindexStep | undefined +): string => { + let percentsComplete = 0; + switch (lastCompletedStep) { + case ReindexStep.created: + // the reindex task has just started, 0% progress + percentsComplete = 0; + break; + case ReindexStep.readonly: { + // step 1 completed, 5% progress + percentsComplete = 5; + break; + } + case ReindexStep.newIndexCreated: { + // step 2 completed, 10% progress + percentsComplete = 10; + break; + } + case ReindexStep.reindexStarted: { + // step 3 started, 10-95% progress depending on progress of reindexing documents in ES + percentsComplete = + reindexTaskPercComplete !== null ? 10 + Math.round(reindexTaskPercComplete * 85) : 10; + break; + } + case ReindexStep.reindexCompleted: { + // step 3 completed, only step 4 remaining, 95% progress + percentsComplete = 95; + break; + } + case ReindexStep.aliasCreated: { + // step 4 completed, 100% progress + percentsComplete = 100; + break; + } + } + return `${percentsComplete}%`; +}; From 458a3185255a318a5a88f451caa108ef199db1b0 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 12 Oct 2021 15:56:17 +0100 Subject: [PATCH 56/93] [Upgrade Assistant] Remove Fix manually heading when there are no manual steps --- .../kibana_deprecations_service.mock.ts | 11 ++++ .../deprecation_details_flyout.test.ts | 12 +++++ .../kibana_deprecation_issues.test.tsx | 2 +- .../deprecation_details_flyout.tsx | 52 ++++++++++--------- 4 files changed, 51 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts index c51e415d7e916..fb0edcdc875d1 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts @@ -34,6 +34,17 @@ const kibanaDeprecations: DomainDeprecationDetails[] = [ message: 'Test deprecation message 2', deprecationType: 'feature', }, + { + correctiveActions: { + // Has no manual steps. + manualSteps: [], + }, + domainId: 'test_domain_3', + level: 'warning', + title: 'Test deprecation title 3', + message: 'Test deprecation message 3', + deprecationType: 'feature', + }, ]; const setLoadDeprecations = ({ diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts index 1b782ae36181c..eb76e3c016a39 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts @@ -61,6 +61,18 @@ describe('Kibana deprecation details flyout', () => { expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe(manualDeprecation.title); expect(find('manualStepsListItem').length).toBe(3); }); + + test(`doesn't show corrective actions title and steps if there aren't any`, async () => { + const { find, exists, actions } = testBed; + const manualDeprecation = mockedKibanaDeprecations[2]; + + await actions.table.clickDeprecationAt(2); + + expect(exists('kibanaDeprecationDetails')).toBe(true); + expect(exists('kibanaDeprecationDetails.manualStepsTitle')).toBe(false); + expect(exists('manualStepsListItem')).toBe(false); + expect(find('kibanaDeprecationDetails.flyoutTitle').text()).toBe(manualDeprecation.title); + }); }); describe('Deprecation with automatic resolution', () => { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx index 3f72542dc33bf..c50797d5f4b7b 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx @@ -57,7 +57,7 @@ describe('Overview - Fix deprecation issues step - Kibana deprecations', () => { expect(exists('kibanaStatsPanel')).toBe(true); expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain(1); - expect(find('kibanaStatsPanel.warningDeprecations').text()).toContain(1); + expect(find('kibanaStatsPanel.warningDeprecations').text()).toContain(2); }); test('panel links to Kibana deprecations page', () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index a1242c2da9b0c..8844386be5081 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -192,31 +192,33 @@ export const DeprecationDetailsFlyout = ({ )} - -

{i18nTexts.manualFixTitle}

-
- - - - - {correctiveActions.manualSteps.length === 1 ? ( -

- {correctiveActions.manualSteps[0]} -

- ) : ( -
    - {correctiveActions.manualSteps.map((step, stepIndex) => ( -
  1. - {step} -
  2. - ))} -
- )} -
+ {correctiveActions.manualSteps.length > 0 && ( + <> + +

{i18nTexts.manualFixTitle}

+
+ + + {correctiveActions.manualSteps.length === 1 ? ( +

+ {correctiveActions.manualSteps[0]} +

+ ) : ( +
    + {correctiveActions.manualSteps.map((step, stepIndex) => ( +
  1. + {step} +
  2. + ))} +
+ )} +
+ + )}
)} From e4a524c950b0396b572b9354da44f5857bc79b3d Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Wed, 13 Oct 2021 05:37:46 -0700 Subject: [PATCH 57/93] Add rolling upgrade interstitials to UA (#112907) * Refactor FixLogsStep to be explicit in which props are passed to DeprecationLoggingToggle. * Centralize error-handling logic in the api service, instead of handling it within each individual API request. Covers: - Cloud backup status - ES deprecations - Deprecation logging - Remove index settings - ML - Reindexing Also: - Handle 426 error state and surface in UI. - Move ResponseError type into common/types. * Add note about intended use case of status API route. * Add endpoint dedicated to surfacing the cluster upgrade state, and a client-side poll. * Merge App and AppWithRouter components. --- .../client_integration/app/app.helpers.tsx | 50 +++++++ .../app/cluster_upgrade.test.tsx | 86 ++++++++++++ .../helpers/app_context.mock.ts | 3 + .../helpers/http_requests.ts | 3 +- .../upgrade_assistant/common/constants.ts | 1 + .../plugins/upgrade_assistant/common/types.ts | 10 ++ .../public/application/app.tsx | 123 +++++++++++++++++- .../index_settings/flyout.tsx | 8 +- .../index_settings/table_row.tsx | 3 +- .../ml_snapshots/use_snapshot_state.tsx | 3 +- .../deprecation_logging_toggle.tsx | 15 ++- .../overview/fix_logs_step/fix_logs_step.tsx | 33 ++++- .../fix_logs_step/use_deprecation_logging.ts | 2 +- .../use_migrate_system_indices.ts | 8 +- .../public/application/components/types.ts | 2 +- .../public/application/lib/api.ts | 110 ++++++++++------ .../lib/get_es_deprecation_error.ts | 2 +- .../public/shared_imports.ts | 1 - .../plugins/upgrade_assistant/public/types.ts | 1 + .../server/routes/cluster_upgrade_status.ts | 21 +++ .../server/routes/register_routes.ts | 2 + .../upgrade_assistant/server/routes/status.ts | 3 + 22 files changed, 419 insertions(+), 71 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/app.helpers.tsx create mode 100644 x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/cluster_upgrade.test.tsx create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/cluster_upgrade_status.ts diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/app.helpers.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/app.helpers.tsx new file mode 100644 index 0000000000000..23726e05b895d --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/app.helpers.tsx @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; +import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; + +import { App } from '../../../public/application/app'; +import { WithAppDependencies } from '../helpers'; + +const testBedConfig: TestBedConfig = { + memoryRouter: { + initialEntries: [`/overview`], + componentRoutePath: '/overview', + }, + doMountAsync: true, +}; + +export type AppTestBed = TestBed & { + actions: ReturnType; +}; + +const createActions = (testBed: TestBed) => { + const clickDeprecationToggle = async () => { + const { find, component } = testBed; + + await act(async () => { + find('deprecationLoggingToggle').simulate('click'); + }); + + component.update(); + }; + + return { + clickDeprecationToggle, + }; +}; + +export const setupAppPage = async (overrides?: Record): Promise => { + const initTestBed = registerTestBed(WithAppDependencies(App, overrides), testBedConfig); + const testBed = await initTestBed(); + + return { + ...testBed, + actions: createActions(testBed), + }; +}; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/cluster_upgrade.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/cluster_upgrade.test.tsx new file mode 100644 index 0000000000000..043c649b39bc2 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/app/cluster_upgrade.test.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; + +import { setupEnvironment } from '../helpers'; +import { AppTestBed, setupAppPage } from './app.helpers'; + +describe('Cluster upgrade', () => { + let testBed: AppTestBed; + let server: ReturnType['server']; + let httpRequestsMockHelpers: ReturnType['httpRequestsMockHelpers']; + + beforeEach(() => { + ({ server, httpRequestsMockHelpers } = setupEnvironment()); + }); + + afterEach(() => { + server.restore(); + }); + + describe('when user is still preparing for upgrade', () => { + beforeEach(async () => { + testBed = await setupAppPage(); + }); + + test('renders overview', () => { + const { exists } = testBed; + expect(exists('overview')).toBe(true); + expect(exists('isUpgradingMessage')).toBe(false); + expect(exists('isUpgradeCompleteMessage')).toBe(false); + }); + }); + + describe('when cluster is in the process of a rolling upgrade', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadDeprecationLoggingResponse(undefined, { + statusCode: 426, + message: '', + attributes: { + allNodesUpgraded: false, + }, + }); + + await act(async () => { + testBed = await setupAppPage(); + }); + }); + + test('renders rolling upgrade message', async () => { + const { component, exists } = testBed; + component.update(); + expect(exists('overview')).toBe(false); + expect(exists('isUpgradingMessage')).toBe(true); + expect(exists('isUpgradeCompleteMessage')).toBe(false); + }); + }); + + describe('when cluster has been upgraded', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadDeprecationLoggingResponse(undefined, { + statusCode: 426, + message: '', + attributes: { + allNodesUpgraded: true, + }, + }); + + await act(async () => { + testBed = await setupAppPage(); + }); + }); + + test('renders upgrade complete message', () => { + const { component, exists } = testBed; + component.update(); + expect(exists('overview')).toBe(false); + expect(exists('isUpgradingMessage')).toBe(false); + expect(exists('isUpgradeCompleteMessage')).toBe(true); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index 46e3deda36fc9..8f142dcdb4b6d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -80,4 +80,7 @@ export const getAppContextMock = () => ({ isCloudEnabled: false, }, }, + clusterUpgradeState: 'isPreparingForUpgrade', + isClusterUpgradeStateError: () => {}, + handleClusterUpgradeStateError: () => {}, }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts index b4ae504fb3b1a..7903ca58ac18a 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/http_requests.ts @@ -6,13 +6,14 @@ */ import sinon, { SinonFakeServer } from 'sinon'; + import { API_BASE_PATH } from '../../../common/constants'; import { CloudBackupStatus, ESUpgradeStatus, DeprecationLoggingStatus, + ResponseError, } from '../../../common/types'; -import { ResponseError } from '../../../public/application/lib/api'; // Register helpers to mock HTTP Requests const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index db8e2a707baa8..0b0a5b57397e0 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -34,6 +34,7 @@ export const DEPRECATION_LOGS_SOURCE_ID = 'deprecation_logs'; export const DEPRECATION_LOGS_INDEX = '.logs-deprecation.elasticsearch-default'; export const DEPRECATION_LOGS_INDEX_PATTERN = '.logs-deprecation.elasticsearch-default'; +export const CLUSTER_UPGRADE_STATUS_POLL_INTERVAL_MS = 45000; export const CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS = 60000; export const DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS = 15000; export const SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS = 15000; diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 1189cfd1866c4..1017ba071ee24 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -10,6 +10,16 @@ import { SavedObject, SavedObjectAttributes } from 'src/core/public'; export type DeprecationSource = 'Kibana' | 'Elasticsearch'; +export type ClusterUpgradeState = 'isPreparingForUpgrade' | 'isUpgrading' | 'isUpgradeComplete'; + +export interface ResponseError { + statusCode: number; + message: string | Error; + attributes?: { + allNodesUpgraded: boolean; + }; +} + export enum ReindexStep { // Enum values are spaced out by 10 to give us room to insert steps in between. created = 0, diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index be2092b46a79a..9ac90e5d81f48 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -5,27 +5,109 @@ * 2.0. */ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiEmptyPrompt, EuiPageContent, EuiLoadingSpinner } from '@elastic/eui'; import { ScopedHistory } from 'src/core/public'; import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; +import { API_BASE_PATH } from '../../common/constants'; +import { ClusterUpgradeState } from '../../common/types'; import { APP_WRAPPER_CLASS, GlobalFlyout, AuthorizationProvider } from '../shared_imports'; import { AppDependencies } from '../types'; -import { API_BASE_PATH } from '../../common/constants'; import { AppContextProvider, useAppContext } from './app_context'; import { EsDeprecations, ComingSoonPrompt, KibanaDeprecations, Overview } from './components'; const { GlobalFlyoutProvider } = GlobalFlyout; -const App: React.FunctionComponent = () => { - const { isReadOnlyMode } = useAppContext(); +const AppHandlingClusterUpgradeState: React.FunctionComponent = () => { + const { + isReadOnlyMode, + services: { api }, + } = useAppContext(); + + const [clusterUpgradeState, setClusterUpradeState] = + useState('isPreparingForUpgrade'); + + useEffect(() => { + api.onClusterUpgradeStateChange((newClusterUpgradeState: ClusterUpgradeState) => { + setClusterUpradeState(newClusterUpgradeState); + }); + }, [api]); // Read-only mode will be enabled up until the last minor before the next major release if (isReadOnlyMode) { return ; } + if (clusterUpgradeState === 'isUpgrading') { + return ( + + + + + } + body={ +

+ +

+ } + data-test-subj="emptyPrompt" + /> +
+ ); + } + + if (clusterUpgradeState === 'isUpgradeComplete') { + return ( + + + + + } + body={ +

+ +

+ } + data-test-subj="emptyPrompt" + /> +
+ ); + } + return ( @@ -36,10 +118,37 @@ const App: React.FunctionComponent = () => { ); }; -export const AppWithRouter = ({ history }: { history: ScopedHistory }) => { +export const App = ({ history }: { history: ScopedHistory }) => { + const { + services: { api }, + } = useAppContext(); + + // Poll the API to detect when the cluster is either in the middle of + // a rolling upgrade or has completed one. We need to create two separate + // components: one to call this hook and one to handle state changes. + // This is because the implementation of this hook calls the state-change + // callbacks on every render, which will get the UI stuck in an infinite + // render loop if the same component both called the hook and handled + // the state changes it triggers. + const { isLoading, isInitialRequest } = api.useLoadClusterUpgradeStatus(); + + // Prevent flicker of the underlying UI while we wait for the status to fetch. + if (isLoading && isInitialRequest) { + return ( + + } /> + + ); + } + return ( - + ); }; @@ -56,7 +165,7 @@ export const RootComponent = (dependencies: AppDependencies) => { - + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx index 24c1897fbdd02..3c19268a293f0 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx @@ -23,8 +23,12 @@ import { EuiSpacer, EuiCallOut, } from '@elastic/eui'; -import { EnrichedDeprecationInfo, IndexSettingAction } from '../../../../../../common/types'; -import type { ResponseError } from '../../../../lib/api'; + +import { + EnrichedDeprecationInfo, + IndexSettingAction, + ResponseError, +} from '../../../../../../common/types'; import type { Status } from '../../../types'; import { DeprecationBadge } from '../../../shared'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx index 997cf476c8378..28fb11334fb3d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/table_row.tsx @@ -7,10 +7,9 @@ import React, { useState, useEffect, useCallback } from 'react'; import { EuiTableRowCell } from '@elastic/eui'; -import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { EnrichedDeprecationInfo, ResponseError } from '../../../../../../common/types'; import { GlobalFlyout } from '../../../../../shared_imports'; import { useAppContext } from '../../../../app_context'; -import type { ResponseError } from '../../../../lib/api'; import { EsDeprecationsTableCells } from '../../es_deprecations_table_cells'; import { DeprecationTableColumns, Status } from '../../../types'; import { IndexSettingsResolutionCell } from './resolution_table_cell'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx index 39f7c3d37ad52..6725ba098e3c9 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/use_snapshot_state.tsx @@ -7,7 +7,8 @@ import { useRef, useCallback, useState, useEffect } from 'react'; -import { ApiService, ResponseError } from '../../../../lib/api'; +import { ResponseError } from '../../../../../../common/types'; +import { ApiService } from '../../../../lib/api'; import { Status } from '../../../types'; const POLL_INTERVAL_MS = 1000; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx index 6de099fe05ef5..0df75a426901e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ResponseError } from '../../../../lib/api'; +import { ResponseError } from '../../../../../../common/types'; import { DeprecationLoggingPreviewProps } from '../../../types'; import './_deprecation_logging_toggle.scss'; @@ -79,7 +79,18 @@ const ErrorDetailsLink = ({ error }: { error: ResponseError }) => { ); }; -export const DeprecationLoggingToggle: FunctionComponent = ({ +type Props = Pick< + DeprecationLoggingPreviewProps, + | 'isDeprecationLogIndexingEnabled' + | 'isLoading' + | 'isUpdating' + | 'fetchError' + | 'updateError' + | 'resendRequest' + | 'toggleLogging' +>; + +export const DeprecationLoggingToggle: FunctionComponent = ({ isDeprecationLogIndexingEnabled, isLoading, isUpdating, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index ee0935e102f9c..42ab75a3ee3f4 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -106,12 +106,23 @@ const FixLogsStep: FunctionComponent = ({ hasPrivileges, privilegesMissing, }) => { - const state = useDeprecationLogging(); const { services: { core: { docLinks }, }, } = useAppContext(); + + const { + isDeprecationLogIndexingEnabled, + onlyDeprecationLogWritingEnabled, + isLoading, + isUpdating, + fetchError, + updateError, + resendRequest, + toggleLogging, + } = useDeprecationLogging(); + const [checkpoint, setCheckpoint] = useState(loadLogsCheckpoint()); useEffect(() => { @@ -119,13 +130,13 @@ const FixLogsStep: FunctionComponent = ({ }, [checkpoint]); useEffect(() => { - if (!state.isDeprecationLogIndexingEnabled) { + if (!isDeprecationLogIndexingEnabled) { setIsComplete(false); } // Depending upon setIsComplete would create an infinite loop. // eslint-disable-next-line react-hooks/exhaustive-deps - }, [state.isDeprecationLogIndexingEnabled]); + }, [isDeprecationLogIndexingEnabled]); return ( <> @@ -134,10 +145,18 @@ const FixLogsStep: FunctionComponent = ({
- + - {state.onlyDeprecationLogWritingEnabled && ( + {onlyDeprecationLogWritingEnabled && ( <> = ({ )} - {!hasPrivileges && state.isDeprecationLogIndexingEnabled && ( + {!hasPrivileges && isDeprecationLogIndexingEnabled && ( <> = ({ )} - {hasPrivileges && state.isDeprecationLogIndexingEnabled && ( + {hasPrivileges && isDeprecationLogIndexingEnabled && ( <> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/use_deprecation_logging.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/use_deprecation_logging.ts index 45ea4e09accfe..e25fd91ae2c52 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/use_deprecation_logging.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/use_deprecation_logging.ts @@ -9,8 +9,8 @@ import { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; +import { ResponseError } from '../../../../../common/types'; import { useAppContext } from '../../../app_context'; -import { ResponseError } from '../../../lib/api'; import { DeprecationLoggingPreviewProps } from '../../types'; const i18nTexts = { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts index d6e9bd2a9d5ff..0d4ea9bfaf35c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts @@ -8,11 +8,11 @@ import { useCallback, useState, useEffect } from 'react'; import useInterval from 'react-use/lib/useInterval'; -import { SystemIndicesFlyout, SystemIndicesFlyoutProps } from './flyout'; -import { useAppContext } from '../../../app_context'; -import type { ResponseError } from '../../../lib/api'; -import { GlobalFlyout } from '../../../../shared_imports'; import { SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS } from '../../../../../common/constants'; +import type { ResponseError } from '../../../../../common/types'; +import { GlobalFlyout } from '../../../../shared_imports'; +import { useAppContext } from '../../../app_context'; +import { SystemIndicesFlyout, SystemIndicesFlyoutProps } from './flyout'; const FLYOUT_ID = 'migrateSystemIndicesFlyout'; const { useGlobalFlyout } = GlobalFlyout; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts index 6b52f7cece514..31dd9cf43656d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ResponseError } from '../lib/api'; +import { ResponseError } from '../../../common/types'; export enum LoadingState { Loading, diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index 24a45fa1018fe..3342435a6d46e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -10,10 +10,13 @@ import { HttpSetup } from 'src/core/public'; import { ESUpgradeStatus, CloudBackupStatus, + ClusterUpgradeState, + ResponseError, SystemIndicesMigrationStatus, } from '../../../common/types'; import { API_BASE_PATH, + CLUSTER_UPGRADE_STATUS_POLL_INTERVAL_MS, DEPRECATION_LOGS_COUNT_POLL_INTERVAL_MS, CLOUD_BACKUP_STATUS_POLL_INTERVAL_MS, } from '../../../common/constants'; @@ -25,35 +28,72 @@ import { useRequest as _useRequest, } from '../../shared_imports'; -export interface ResponseError { - statusCode: number; - message: string | Error; - attributes?: Record; -} +type ClusterUpgradeStateListener = (clusterUpgradeState: ClusterUpgradeState) => void; export class ApiService { private client: HttpSetup | undefined; - - private useRequest(config: UseRequestConfig) { - if (!this.client) { - throw new Error('API service has not be initialized.'); + private clusterUpgradeStateListeners: ClusterUpgradeStateListener[] = []; + + private handleClusterUpgradeError(error: ResponseError | null) { + const isClusterUpgradeError = Boolean(error && error.statusCode === 426); + if (isClusterUpgradeError) { + const clusterUpgradeState = error!.attributes!.allNodesUpgraded + ? 'isUpgradeComplete' + : 'isUpgrading'; + this.clusterUpgradeStateListeners.forEach((listener) => listener(clusterUpgradeState)); } - return _useRequest(this.client, config); } - private sendRequest( + private useRequest(config: UseRequestConfig) { + if (!this.client) { + throw new Error('API service has not been initialized.'); + } + const response = _useRequest(this.client, config); + // NOTE: This will cause an infinite render loop in any component that both + // consumes the hook calling this useRequest function and also handles + // cluster upgrade errors. Note that sendRequest doesn't have this problem. + // + // This is due to React's fundamental expectation that hooks be idempotent, + // so it can render a component as many times as necessary and thereby call + // the hook on each render without worrying about that triggering subsequent + // renders. + // + // In this case we call handleClusterUpgradeError every time useRequest is + // called, which is on every render. If handling the cluster upgrade error + // causes a state change in the consuming component, that will trigger a + // render, which will call useRequest again, calling handleClusterUpgradeError, + // causing a state change in the consuming component, and so on. + this.handleClusterUpgradeError(response.error); + return response; + } + + private async sendRequest( config: SendRequestConfig - ): Promise> { + ): Promise> { if (!this.client) { - throw new Error('API service has not be initialized.'); + throw new Error('API service has not been initialized.'); } - return _sendRequest(this.client, config); + const response = await _sendRequest(this.client, config); + this.handleClusterUpgradeError(response.error); + return response; } public setup(httpClient: HttpSetup): void { this.client = httpClient; } + public onClusterUpgradeStateChange(listener: ClusterUpgradeStateListener) { + this.clusterUpgradeStateListeners.push(listener); + } + + public useLoadClusterUpgradeStatus() { + return this.useRequest({ + path: `${API_BASE_PATH}/cluster_upgrade_status`, + method: 'get', + pollIntervalMs: CLUSTER_UPGRADE_STATUS_POLL_INTERVAL_MS, + }); + } + public useLoadCloudBackupStatus() { return this.useRequest({ path: `${API_BASE_PATH}/cloud_backup_status`, @@ -86,13 +126,11 @@ export class ApiService { } public async sendPageTelemetryData(telemetryData: { [tabName: string]: boolean }) { - const result = await this.sendRequest({ + return await this.sendRequest({ path: `${API_BASE_PATH}/stats/ui_open`, method: 'put', body: JSON.stringify(telemetryData), }); - - return result; } public useLoadDeprecationLogging() { @@ -106,13 +144,11 @@ export class ApiService { } public async updateDeprecationLogging(loggingData: { isEnabled: boolean }) { - const result = await this.sendRequest({ + return await this.sendRequest({ path: `${API_BASE_PATH}/deprecation_logging`, method: 'put', body: JSON.stringify(loggingData), }); - - return result; } public getDeprecationLogsCount(from: string) { @@ -134,34 +170,28 @@ export class ApiService { } public async updateIndexSettings(indexName: string, settings: string[]) { - const result = await this.sendRequest({ + return await this.sendRequest({ path: `${API_BASE_PATH}/${indexName}/index_settings`, method: 'post', body: { settings: JSON.stringify(settings), }, }); - - return result; } public async upgradeMlSnapshot(body: { jobId: string; snapshotId: string }) { - const result = await this.sendRequest({ + return await this.sendRequest({ path: `${API_BASE_PATH}/ml_snapshots`, method: 'post', body, }); - - return result; } public async deleteMlSnapshot({ jobId, snapshotId }: { jobId: string; snapshotId: string }) { - const result = await this.sendRequest({ + return await this.sendRequest({ path: `${API_BASE_PATH}/ml_snapshots/${jobId}/${snapshotId}`, method: 'delete', }); - - return result; } public async getMlSnapshotUpgradeStatus({ @@ -177,14 +207,21 @@ export class ApiService { }); } + public useLoadMlUpgradeMode() { + return this.useRequest<{ + mlUpgradeModeEnabled: boolean; + }>({ + path: `${API_BASE_PATH}/ml_upgrade_mode`, + method: 'get', + }); + } + public async sendReindexTelemetryData(telemetryData: { [key: string]: boolean }) { - const result = await this.sendRequest({ + return await this.sendRequest({ path: `${API_BASE_PATH}/stats/ui_reindex`, method: 'put', body: JSON.stringify(telemetryData), }); - - return result; } public async getReindexStatus(indexName: string) { @@ -207,15 +244,6 @@ export class ApiService { method: 'post', }); } - - public useLoadMlUpgradeMode() { - return this.useRequest<{ - mlUpgradeModeEnabled: boolean; - }>({ - path: `${API_BASE_PATH}/ml_upgrade_mode`, - method: 'get', - }); - } } export const apiService = new ApiService(); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts index 889568fb7a412..9581ce872a288 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/get_es_deprecation_error.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ResponseError } from './api'; +import { ResponseError } from '../../../common/types'; const i18nTexts = { permissionsError: i18n.translate( diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index 1d0b1ae51f30f..8fbf87c105214 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -11,7 +11,6 @@ export { SendRequestResponse, useRequest, UseRequestConfig, - UseRequestResponse, SectionLoading, GlobalFlyout, WithPrivileges, diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index 4d47c10fdeec2..a0e6c5f7d1dff 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -10,6 +10,7 @@ import { ManagementSetup } from 'src/plugins/management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SharePluginSetup } from 'src/plugins/share/public'; import { CoreStart } from 'src/core/public'; + import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; import { BreadcrumbService } from './application/lib/breadcrumbs'; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/cluster_upgrade_status.ts b/x-pack/plugins/upgrade_assistant/server/routes/cluster_upgrade_status.ts new file mode 100644 index 0000000000000..4ae1205d2daef --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/cluster_upgrade_status.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { API_BASE_PATH } from '../../common/constants'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { RouteDependencies } from '../types'; + +export function registerClusterUpgradeStatusRoutes({ router }: RouteDependencies) { + router.get( + { path: `${API_BASE_PATH}/cluster_upgrade_status`, validate: false }, + // We're just depending on the version check to return a 426. + // Otherwise we just return a 200. + versionCheckHandlerWrapper(async (context, request, response) => { + return response.ok(); + }) + ); +} diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index ec02e814b2a8d..e6a92af53b143 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -9,6 +9,7 @@ import { RouteDependencies } from '../types'; import { registerAppRoutes } from './app'; import { registerCloudBackupStatusRoutes } from './cloud_backup_status'; +import { registerClusterUpgradeStatusRoutes } from './cluster_upgrade_status'; import { registerSystemIndicesMigrationRoutes } from './system_indices_migration'; import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; @@ -22,6 +23,7 @@ import { registerUpgradeStatusRoute } from './status'; export function registerRoutes(dependencies: RouteDependencies, getWorker: () => ReindexWorker) { registerAppRoutes(dependencies); registerCloudBackupStatusRoutes(dependencies); + registerClusterUpgradeStatusRoutes(dependencies); registerSystemIndicesMigrationRoutes(dependencies); registerESDeprecationRoutes(dependencies); registerDeprecationLoggingRoutes(dependencies); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.ts index aef97dcb7bd71..ce9bb2e1c55d0 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.ts @@ -12,6 +12,9 @@ import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { getKibanaUpgradeStatus } from '../lib/kibana_status'; import { RouteDependencies } from '../types'; +/** + * Note that this route is primarily intended for consumption by Cloud. + */ export function registerUpgradeStatusRoute({ router, lib: { handleEsError } }: RouteDependencies) { router.get( { From cf8418fcaf397cdbbf180d374c8db48508b54938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Wed, 13 Oct 2021 18:02:04 +0200 Subject: [PATCH 58/93] [Upgrade Assistant] Added "accept changes" header to the warnings list in the reindex flyout (#114798) --- .../flyout/__snapshots__/warning_step.test.tsx.snap | 12 ++++++++++++ .../reindex/flyout/warnings_step.tsx | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap index d085e5ecc20ed..bec337087e534 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap @@ -23,6 +23,18 @@ exports[`WarningsFlyoutStep renders 1`] = `

+ +

+ +

+
+
+ + +

+ +

+
{warnings.map((warning, index) => { From c92cb20b2277d660bdbf1a9faff8705f8b27628c Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 14 Oct 2021 08:17:53 +0100 Subject: [PATCH 59/93] Refactor kibana deprecation tests (#114763) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../client_integration/helpers/index.ts | 1 - .../deprecation_details_flyout.test.ts | 18 +++++++++++++++--- .../deprecations_table.test.ts} | 7 ++++--- .../error_handling.test.ts | 7 ++++--- .../service.mock.ts} | 1 + .../elasticsearch_deprecation_issues.test.tsx | 3 ++- .../fix_issues_step/fix_issues_step.test.tsx | 3 ++- .../kibana_deprecation_issues.test.tsx | 3 ++- .../deprecation_details_flyout.tsx | 2 +- 9 files changed, 31 insertions(+), 14 deletions(-) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/{ => deprecation_details_flyout}/deprecation_details_flyout.test.ts (89%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/{deprecations_list.test.ts => deprecations_table/deprecations_table.test.ts} (93%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/{ => deprecations_table}/error_handling.test.ts (91%) rename x-pack/plugins/upgrade_assistant/__jest__/client_integration/{helpers/kibana_deprecations_service.mock.ts => kibana_deprecations/service.mock.ts} (98%) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts index 8b8cadac70c48..f70bfd00e9c07 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts @@ -7,4 +7,3 @@ export { setupEnvironment, WithAppDependencies, kibanaVersion } from './setup_environment'; export { advanceTime } from './time_manipulation'; -export { kibanaDeprecationsServiceHelpers } from './kibana_deprecations_service.mock'; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout/deprecation_details_flyout.test.ts similarity index 89% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout/deprecation_details_flyout.test.ts index eb76e3c016a39..9677104a6e558 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecation_details_flyout/deprecation_details_flyout.test.ts @@ -8,10 +8,11 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; -import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../helpers'; -import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { setupEnvironment } from '../../helpers'; +import { kibanaDeprecationsServiceHelpers } from '../service.mock'; +import { KibanaTestBed, setupKibanaPage } from '../kibana_deprecations.helpers'; -describe('Kibana deprecation details flyout', () => { +describe('Kibana deprecations - Deprecation details flyout', () => { let testBed: KibanaTestBed; const { server } = setupEnvironment(); const { @@ -75,6 +76,17 @@ describe('Kibana deprecation details flyout', () => { }); }); + test('Shows documentationUrl when present', async () => { + const { find, actions } = testBed; + const deprecation = mockedKibanaDeprecations[1]; + + await actions.table.clickDeprecationAt(1); + + expect(find('kibanaDeprecationDetails.documentationLink').props().href).toBe( + deprecation.documentationUrl + ); + }); + describe('Deprecation with automatic resolution', () => { test('resolves deprecation successfully', async () => { const { find, exists, actions } = testBed; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/deprecations_table.test.ts similarity index 93% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/deprecations_table.test.ts index 9a3b1d1882cc7..a14d6e087b017 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/deprecations_table.test.ts @@ -9,10 +9,11 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; import type { DeprecationsServiceStart } from 'kibana/public'; -import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../helpers'; -import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { setupEnvironment } from '../../helpers'; +import { kibanaDeprecationsServiceHelpers } from '../service.mock'; +import { KibanaTestBed, setupKibanaPage } from '../kibana_deprecations.helpers'; -describe('Kibana deprecations table', () => { +describe('Kibana deprecations - Deprecations table', () => { let testBed: KibanaTestBed; let deprecationService: jest.Mocked; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/error_handling.test.ts similarity index 91% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/error_handling.test.ts index 650af2025ee2b..918ee759a0f45 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/error_handling.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/deprecations_table/error_handling.test.ts @@ -8,10 +8,11 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; -import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../helpers'; -import { KibanaTestBed, setupKibanaPage } from './kibana_deprecations.helpers'; +import { setupEnvironment } from '../../helpers'; +import { kibanaDeprecationsServiceHelpers } from '../service.mock'; +import { KibanaTestBed, setupKibanaPage } from '../kibana_deprecations.helpers'; -describe('Error handling', () => { +describe('Kibana deprecations - Deprecations table - Error handling', () => { let testBed: KibanaTestBed; const { server } = setupEnvironment(); const deprecationService = deprecationsServiceMock.createStartContract(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts similarity index 98% rename from x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts rename to x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts index fb0edcdc875d1..1767143fdf527 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/kibana_deprecations_service.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts @@ -31,6 +31,7 @@ const kibanaDeprecations: DomainDeprecationDetails[] = [ domainId: 'test_domain_2', level: 'warning', title: 'Test deprecation title 1', + documentationUrl: 'https://', message: 'Test deprecation message 2', deprecationType: 'feature', }, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx index bbb8b049ec2b8..e1cef64dfb20c 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/elasticsearch_deprecation_issues.test.tsx @@ -8,7 +8,8 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; -import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../../helpers'; +import { setupEnvironment } from '../../helpers'; +import { kibanaDeprecationsServiceHelpers } from '../../kibana_deprecations/service.mock'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; import { esCriticalAndWarningDeprecations, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx index e9fa57b54ae0e..b7c417fbfcb8d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/fix_issues_step.test.tsx @@ -8,7 +8,8 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; -import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../../helpers'; +import { setupEnvironment } from '../../helpers'; +import { kibanaDeprecationsServiceHelpers } from '../../kibana_deprecations/service.mock'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; import { esCriticalAndWarningDeprecations, esNoDeprecations } from './mock_es_issues'; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx index c50797d5f4b7b..6b630d5c2c1fc 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx @@ -9,7 +9,8 @@ import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; import type { DomainDeprecationDetails } from 'kibana/public'; -import { setupEnvironment, kibanaDeprecationsServiceHelpers } from '../../helpers'; +import { setupEnvironment } from '../../helpers'; +import { kibanaDeprecationsServiceHelpers } from '../../kibana_deprecations/service.mock'; import { OverviewTestBed, setupOverviewPage } from '../overview.helpers'; import { esNoDeprecations } from './mock_es_issues'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index 8844386be5081..577354b35fa4e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -165,7 +165,7 @@ export const DeprecationDetailsFlyout = ({ {documentationUrl && (

- + {i18nTexts.learnMoreLinkLabel}

From b376794232b6461e66317671864d97eec4e83ddb Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 14 Oct 2021 11:25:12 +0200 Subject: [PATCH 60/93] Fix linter issues --- .../public/doc_links/doc_links_service.ts | 3 -- .../kibana_deprecation_issues.test.tsx | 6 ++-- .../fix_issues_step/mock_es_issues.ts | 3 +- .../es_deprecations/es_deprecations.tsx | 7 ++-- .../kibana_deprecations.tsx | 6 ++-- .../overview/backup_step/cloud_backup.tsx | 9 ++---- .../deprecations_count_checkpoint.tsx | 5 ++- .../server/routes/deprecation_logging.test.ts | 32 ++++++++++++------- 8 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index a9f13c722e5ec..112fac973bc8d 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -223,13 +223,10 @@ export class DocLinksService { remoteClustersProxy: `${ELASTICSEARCH_DOCS}remote-clusters.html#proxy-mode`, remoteClusersProxySettings: `${ELASTICSEARCH_DOCS}remote-clusters-settings.html#remote-cluster-proxy-settings`, scriptParameters: `${ELASTICSEARCH_DOCS}modules-scripting-using.html#prefer-params`, - setupUpgrade: `${ELASTICSEARCH_DOCS}setup-upgrade.html`, shardAllocationSettings: `${ELASTICSEARCH_DOCS}modules-cluster.html#cluster-shard-allocation-settings`, transportSettings: `${ELASTICSEARCH_DOCS}modules-network.html#common-network-settings`, typesRemoval: `${ELASTICSEARCH_DOCS}removal-of-types.html`, - deprecationLogging: `${ELASTICSEARCH_DOCS}logging.html#deprecation-logging`, setupUpgrade: `${ELASTICSEARCH_DOCS}setup-upgrade.html`, - releaseHighlights: `${ELASTICSEARCH_DOCS}release-highlights.html`, apiCompatibilityHeader: `${ELASTICSEARCH_DOCS}api-conventions.html#api-compatibility`, }, siem: { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx index 6b630d5c2c1fc..c11a1481b68b5 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/kibana_deprecation_issues.test.tsx @@ -17,10 +17,8 @@ import { esNoDeprecations } from './mock_es_issues'; describe('Overview - Fix deprecation issues step - Kibana deprecations', () => { let testBed: OverviewTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); - const { - mockedKibanaDeprecations, - mockedCriticalKibanaDeprecations, - } = kibanaDeprecationsServiceHelpers.defaultMockedResponses; + const { mockedKibanaDeprecations, mockedCriticalKibanaDeprecations } = + kibanaDeprecationsServiceHelpers.defaultMockedResponses; afterAll(() => { server.restore(); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts index e3fd9a2dad693..13505b47c5a7f 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts @@ -40,8 +40,7 @@ export const esCriticalOnlyDeprecations: ESUpgradeStatus = { type: 'cluster_settings', resolveDuringUpgrade: false, message: 'Index Lifecycle Management poll interval is set too low', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#ilm-poll-interval-limit', + url: 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#ilm-poll-interval-limit', details: 'The Index Lifecycle Management poll interval setting [indices.lifecycle.poll_interval] is currently set to [500ms], but must be 1s or greater', }, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 09f7eaf298f55..c7d157c342c77 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -93,9 +93,10 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { const deprecationsCountByLevel: { warningDeprecations: number; criticalDeprecations: number; - } = useMemo(() => getDeprecationCountByLevel(esDeprecations?.deprecations || []), [ - esDeprecations?.deprecations, - ]); + } = useMemo( + () => getDeprecationCountByLevel(esDeprecations?.deprecations || []), + [esDeprecations?.deprecations] + ); useEffect(() => { breadcrumbs.setBreadcrumbs('esDeprecations'); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 8158f8462da1e..23697b00923c8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -120,10 +120,8 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) }, } = useAppContext(); - const { - addContent: addContentToGlobalFlyout, - removeContent: removeContentFromGlobalFlyout, - } = useGlobalFlyout(); + const { addContent: addContentToGlobalFlyout, removeContent: removeContentFromGlobalFlyout } = + useGlobalFlyout(); const getAllDeprecations = useCallback(async () => { setIsLoading(true); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx index abef34a27f30f..55a6ee8e5c73f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx @@ -35,13 +35,8 @@ export const CloudBackup: React.FunctionComponent = ({ services: { api }, } = useAppContext(); - const { - isInitialRequest, - isLoading, - error, - data, - resendRequest, - } = api.useLoadCloudBackupStatus(); + const { isInitialRequest, isLoading, error, data, resendRequest } = + api.useLoadCloudBackupStatus(); // Tell overview whether the step is complete or not. useEffect(() => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx index c200884e94699..e444c6f35348b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -67,9 +67,8 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ core: { notifications }, }, } = useAppContext(); - const { data, error, isLoading, resendRequest, isInitialRequest } = api.getDeprecationLogsCount( - checkpoint - ); + const { data, error, isLoading, resendRequest, isInitialRequest } = + api.getDeprecationLogsCount(checkpoint); const logsCount = data?.count || 0; const hasLogs = logsCount > 0; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts index 1315e503732e3..fc61832e69c12 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts @@ -64,8 +64,10 @@ describe('deprecation logging API', () => { }); it('returns an error if it throws', async () => { - (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster - .getSettings as jest.Mock).mockRejectedValue(new Error('scary error!')); + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .getSettings as jest.Mock + ).mockRejectedValue(new Error('scary error!')); await expect( routeDependencies.router.getHandler({ method: 'get', @@ -101,8 +103,10 @@ describe('deprecation logging API', () => { }); it('returns an error if it throws', async () => { - (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster - .putSettings as jest.Mock).mockRejectedValue(new Error('scary error!')); + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.cluster + .putSettings as jest.Mock + ).mockRejectedValue(new Error('scary error!')); await expect( routeDependencies.router.getHandler({ method: 'put', @@ -116,12 +120,14 @@ describe('deprecation logging API', () => { const MOCK_FROM_DATE = '2021-08-23T07:32:34.782Z'; it('returns count of deprecations', async () => { - (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices - .exists as jest.Mock).mockResolvedValue({ + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices.exists as jest.Mock + ).mockResolvedValue({ body: true, }); - (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser - .count as jest.Mock).mockResolvedValue({ + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.count as jest.Mock + ).mockResolvedValue({ body: { count: 10 }, }); @@ -139,8 +145,9 @@ describe('deprecation logging API', () => { }); it('returns zero matches when deprecation logs index is not created', async () => { - (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices - .exists as jest.Mock).mockResolvedValue({ + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices.exists as jest.Mock + ).mockResolvedValue({ body: false, }); @@ -158,8 +165,9 @@ describe('deprecation logging API', () => { }); it('returns an error if it throws', async () => { - (routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices - .exists as jest.Mock).mockRejectedValue(new Error('scary error!')); + ( + routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.indices.exists as jest.Mock + ).mockRejectedValue(new Error('scary error!')); await expect( routeDependencies.router.getHandler({ method: 'get', From 0b0bbd0c9e85c622da88007ee863e9d75056a65e Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 14 Oct 2021 11:45:17 +0200 Subject: [PATCH 61/93] Remove unused translation --- x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a0ff61f13ee3d..695da2345994b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25238,7 +25238,6 @@ "xpack.upgradeAssistant.overview.observe.observabilityDescription": "使用中のAPIのうち廃止予定のAPIと、更新が必要なアプリケーションを特定できます。", "xpack.upgradeAssistant.overview.pageDescription": "次のバージョンのElastic Stackをお待ちください。", "xpack.upgradeAssistant.overview.pageTitle": "アップグレードアシスタント", - "xpack.upgradeAssistant.overview.reviewStepTitle": "廃止予定設定を確認し、問題を解決", "xpack.upgradeAssistant.overview.toggleTitle": "Elasticsearch廃止予定警告をログに出力", "xpack.upgradeAssistant.overview.upgradeGuideLink": "アップグレードガイドを表示", "xpack.upgradeAssistant.overview.upgradeStepCloudLink": "クラウドでアップグレード", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c497c81630507..847bebb961fe6 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25667,7 +25667,6 @@ "xpack.upgradeAssistant.overview.observe.observabilityDescription": "深入了解正在使用哪些已弃用 API 以及需要更新哪些应用程序。", "xpack.upgradeAssistant.overview.pageDescription": "准备使用下一版 Elastic Stack!", "xpack.upgradeAssistant.overview.pageTitle": "升级助手", - "xpack.upgradeAssistant.overview.reviewStepTitle": "复查已弃用设置并解决问题", "xpack.upgradeAssistant.overview.toggleTitle": "记录 Elasticsearch 弃用警告", "xpack.upgradeAssistant.overview.upgradeGuideLink": "查看升级指南", "xpack.upgradeAssistant.overview.upgradeStepCloudLink": "在 Cloud 上升级", From 11ee3d2cdf1d71115bee7b2fcd10add5284390d8 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 14 Oct 2021 12:08:39 +0200 Subject: [PATCH 62/93] Prefer master changes over 7.x for ml docs --- src/core/public/doc_links/doc_links_service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 112fac973bc8d..a18b7c8a24632 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -288,9 +288,9 @@ export class DocLinksService { customUrls: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-configuring-url.html`, dataFrameAnalytics: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics.html`, featureImportance: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-feature-importance.html`, - outlierDetectionRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-roc`, - regressionEvaluation: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-regression-evaluation`, - classificationAucRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-class-aucroc`, + outlierDetectionRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfa-finding-outliers.html#ml-dfanalytics-roc`, + regressionEvaluation: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfa-regression.html#ml-dfanalytics-regression-evaluation`, + classificationAucRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfa-classification.html#ml-dfanalytics-class-aucroc`, setUpgradeMode: `${ELASTICSEARCH_DOCS}ml-set-upgrade-mode.html`, }, transforms: { From e90d37f21c68f19eee4322f512b97efb4102b380 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 14 Oct 2021 13:16:42 +0200 Subject: [PATCH 63/93] Prefer master changes over 7.x --- x-pack/plugins/snapshot_restore/public/locator.ts | 3 ++- .../functional/apps/upgrade_assistant/deprecation_pages.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/snapshot_restore/public/locator.ts b/x-pack/plugins/snapshot_restore/public/locator.ts index ba57446a03887..fac7d389d8e96 100644 --- a/x-pack/plugins/snapshot_restore/public/locator.ts +++ b/x-pack/plugins/snapshot_restore/public/locator.ts @@ -22,7 +22,8 @@ export interface SnapshotRestoreLocatorDefinitionDependencies { } export class SnapshotRestoreLocatorDefinition - implements LocatorDefinition { + implements LocatorDefinition +{ constructor(protected readonly deps: SnapshotRestoreLocatorDefinitionDependencies) {} public readonly id = SNAPSHOT_RESTORE_LOCATOR_ID; diff --git a/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts index ab989b0dabb83..a32a795ee0960 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts @@ -50,6 +50,7 @@ export default function upgradeAssistantFunctionalTests({ }: FtrProviderContext) { const PageObjects = getPageObjects(['upgradeAssistant', 'common']); const retry = getService('retry'); + const security = getService('security'); const testSubjects = getService('testSubjects'); const es = getService('es'); const security = getService('security'); From 38721baec6b5265df16ecaefad81fd0e7b1e91ef Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 14 Oct 2021 16:42:22 +0200 Subject: [PATCH 64/93] Skip tests --- .../apps/upgrade_assistant/overview_page.ts | 8 +++++--- x-pack/test/functional/config.js | 11 +---------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts index 76663a9f57c89..c1549055e4550 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts @@ -30,20 +30,22 @@ export default function upgradeAssistantOverviewPageFunctionalTests({ beforeEach(async () => { await PageObjects.upgradeAssistant.navigateToPage(); + }); + it('shows coming soon prompt', async () => { await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { - return testSubjects.exists('overview'); + return testSubjects.exists('comingSoonPrompt'); }); }); - it('Should render all steps', async () => { + it.skip('Should render all steps', async () => { testSubjects.exists('backupStep-incomplete'); testSubjects.exists('fixIssuesStep-incomplete'); testSubjects.exists('fixLogsStep-incomplete'); testSubjects.exists('upgradeStep'); }); - describe('fixLogsStep', () => { + describe.skip('fixLogsStep', () => { before(async () => { // Access to system indices will be deprecated and should generate a deprecation log await es.indices.get({ index: '.kibana' }); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index 8825c5796496f..2abd91fd0433a 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -86,9 +86,6 @@ export default async function ({ readConfigFile }) { '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', '--xpack.discoverEnhanced.actions.exploreDataInContextMenu.enabled=true', '--savedObjects.maxImportPayloadBytes=10485760', // for OSS test management/_import_objects - '--xpack.observability.unsafe.cases.enabled=true', - '--xpack.siem.enabled=true', // Used to trigger Kibana deprecation warning in UA (renamed config) - '--xpack.observability.unsafe.alertingExperience.enabled=true', // NOTE: Can be removed once enabled by default ], }, uiSettings: { @@ -441,13 +438,7 @@ export default async function ({ readConfigFile }) { // using this role even for remote clusters global_ccr_role: { elasticsearch: { - cluster: ['manage'], - indices: [ - { - names: ['*'], - privileges: ['view_index_metadata'], - }, - ], + cluster: ['manage', 'manage_ccr'], }, kibana: [ { From 528290aa37b60b485169da958d1ed47994120a94 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Fri, 15 Oct 2021 15:18:17 +0200 Subject: [PATCH 65/93] Move everything to a single describe --- .../accessibility/apps/upgrade_assistant.ts | 172 ++++++++++-------- 1 file changed, 99 insertions(+), 73 deletions(-) diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 38ade6e908859..72899854f4b30 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -76,102 +76,128 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } }); - describe('Overview page', () => { - beforeEach(async () => { + describe('Upgrade Assistant - Overview', () => { + before(async () => { await PageObjects.upgradeAssistant.navigateToPage(); - await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { - return testSubjects.exists('overview'); - }); + + try { + // Create two indices that will trigger deprecation warnings to test the ES deprecations page + await es.indices.create(multiFieldsIndexDeprecation); + await es.indices.create(translogSettingsIndexDeprecation); + } catch (e) { + log.debug('[Setup error] Error creating indices'); + throw e; + } }); - it('with logs collection disabled', async () => { - await a11y.testAppSnapshot(); + after(async () => { + try { + await es.indices.delete({ + index: [multiFieldsIndexDeprecation.index, translogSettingsIndexDeprecation.index], + }); + } catch (e) { + log.debug('[Cleanup error] Error deleting indices'); + throw e; + } }); - it('with logs collection enabled', async () => { - await PageObjects.upgradeAssistant.clickDeprecationLoggingToggle(); + describe('Overview page', () => { + beforeEach(async () => { + await PageObjects.upgradeAssistant.navigateToPage(); + await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { + return testSubjects.exists('overview'); + }); + }); - await retry.waitFor('UA external links title to be present', async () => { - return testSubjects.isDisplayed('externalLinksTitle'); + it('with logs collection disabled', async () => { + await a11y.testAppSnapshot(); }); - await a11y.testAppSnapshot(); - }); - }); + it('with logs collection enabled', async () => { + await PageObjects.upgradeAssistant.clickDeprecationLoggingToggle(); - describe('Elasticsearch deprecations page', () => { - beforeEach(async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/es_deprecations', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); - - await retry.waitFor('Elasticsearch deprecations table to be visible', async () => { - return testSubjects.exists('esDeprecationsTable'); - }); - }); + await retry.waitFor('UA external links title to be present', async () => { + return testSubjects.isDisplayed('externalLinksTitle'); + }); - it('Deprecations table', async () => { - await a11y.testAppSnapshot(); + await a11y.testAppSnapshot(); + }); }); - it('Index settings deprecation flyout', async () => { - await PageObjects.upgradeAssistant.clickEsDeprecation( - 'indexSettings' // An index setting deprecation was added in the before() hook so should be guaranteed - ); - await retry.waitFor('ES index settings deprecation flyout to be visible', async () => { - return testSubjects.exists('indexSettingsDetails'); + describe('Elasticsearch deprecations page', () => { + beforeEach(async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/es_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); + + await retry.waitFor('Elasticsearch deprecations table to be visible', async () => { + return testSubjects.exists('esDeprecationsTable'); + }); }); - await a11y.testAppSnapshot(); - }); - it('Default deprecation flyout', async () => { - await PageObjects.upgradeAssistant.clickEsDeprecation( - 'default' // A default deprecation was added in the before() hook so should be guaranteed - ); - await retry.waitFor('ES default deprecation flyout to be visible', async () => { - return testSubjects.exists('defaultDeprecationDetails'); + it('Deprecations table', async () => { + await a11y.testAppSnapshot(); }); - await a11y.testAppSnapshot(); - }); - }); - describe('Kibana deprecations page', () => { - beforeEach(async () => { - await PageObjects.common.navigateToUrl( - 'management', - 'stack/upgrade_assistant/kibana_deprecations', - { - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - } - ); - - await retry.waitFor('Kibana deprecations to be visible', async () => { - return testSubjects.exists('kibanaDeprecations'); + it('Index settings deprecation flyout', async () => { + await PageObjects.upgradeAssistant.clickEsDeprecation( + 'indexSettings' // An index setting deprecation was added in the before() hook so should be guaranteed + ); + await retry.waitFor('ES index settings deprecation flyout to be visible', async () => { + return testSubjects.exists('indexSettingsDetails'); + }); + await a11y.testAppSnapshot(); }); - }); - it('Deprecations table', async () => { - await a11y.testAppSnapshot(); + it('Default deprecation flyout', async () => { + await PageObjects.upgradeAssistant.clickEsDeprecation( + 'default' // A default deprecation was added in the before() hook so should be guaranteed + ); + await retry.waitFor('ES default deprecation flyout to be visible', async () => { + return testSubjects.exists('defaultDeprecationDetails'); + }); + await a11y.testAppSnapshot(); + }); }); - it('Deprecation details flyout', async () => { - await PageObjects.upgradeAssistant.clickKibanaDeprecation( - 'xpack.securitySolution has a deprecated setting' // This deprecation was added to the test runner config so should be guaranteed - ); + describe('Kibana deprecations page', () => { + beforeEach(async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/kibana_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); + + await retry.waitFor('Kibana deprecations to be visible', async () => { + return testSubjects.exists('kibanaDeprecations'); + }); + }); - await retry.waitFor('Kibana deprecation details flyout to be visible', async () => { - return testSubjects.exists('kibanaDeprecationDetails'); + it('Deprecations table', async () => { + await a11y.testAppSnapshot(); }); - await a11y.testAppSnapshot(); + it('Deprecation details flyout', async () => { + await PageObjects.upgradeAssistant.clickKibanaDeprecation( + 'xpack.securitySolution has a deprecated setting' // This deprecation was added to the test runner config so should be guaranteed + ); + + await retry.waitFor('Kibana deprecation details flyout to be visible', async () => { + return testSubjects.exists('kibanaDeprecationDetails'); + }); + + await a11y.testAppSnapshot(); + }); }); }); }); From d6270f6ea4708e37fa7de71c4cacc46c0312ed6d Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 18 Oct 2021 09:53:41 +0200 Subject: [PATCH 66/93] Fix types --- .../client_integration/kibana_deprecations/service.mock.ts | 2 +- .../components/kibana_deprecations/kibana_deprecations.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts index 1767143fdf527..af78d3f921f25 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts @@ -21,7 +21,7 @@ const kibanaDeprecations: DomainDeprecationDetails[] = [ level: 'critical', title: 'Test deprecation title 1', message: 'Test deprecation message 1', - deprecationType: 'config', + deprecationType: 'feature', }, { correctiveActions: { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 23697b00923c8..013f59a7dcf56 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -75,10 +75,10 @@ export interface DeprecationResolutionState { resolveDeprecationError?: string; } -export interface KibanaDeprecationDetails extends DomainDeprecationDetails { +export type KibanaDeprecationDetails = DomainDeprecationDetails & { id: string; filterType: DomainDeprecationDetails['deprecationType'] | 'uncategorized'; -} +}; const getDeprecationCountByLevel = (deprecations: KibanaDeprecationDetails[]) => { const criticalDeprecations: KibanaDeprecationDetails[] = []; From 03cb4aea0d8096a1671284cf39a2f302bd543a63 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 18 Oct 2021 11:25:55 +0200 Subject: [PATCH 67/93] Add missing prop to mock --- .../client_integration/kibana_deprecations/service.mock.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts index af78d3f921f25..dc8bfdddf1964 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts @@ -21,7 +21,8 @@ const kibanaDeprecations: DomainDeprecationDetails[] = [ level: 'critical', title: 'Test deprecation title 1', message: 'Test deprecation message 1', - deprecationType: 'feature', + deprecationType: 'config', + configPath: 'path', }, { correctiveActions: { From 150a4276f502d7078da7f3b3de7de451749c74fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Thu, 14 Oct 2021 10:47:15 +0200 Subject: [PATCH 68/93] [Upgrade Assistant] Removed "closed index" warning from reindex flyout (#114861) * [Upgrade Assistant] Removed "closed index" warning that reindexing might take longer than usual, which is not the case * [Upgrade Assistant] Also deleted i18n strings that are not needed anymore --- .../translations/translations/ja-JP.json | 4 -- .../translations/translations/zh-CN.json | 4 -- .../reindex/flyout/checklist_step.tsx | 4 +- .../reindex/flyout/container.tsx | 67 ++----------------- .../reindex/flyout/warnings_step.tsx | 4 -- 5 files changed, 5 insertions(+), 78 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 695da2345994b..7b8dd06682d33 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25186,10 +25186,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.readonlyStepTitle": "古いインデックスを読み込み専用に設定中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.reindexingDocumentsStepTitle": "ドキュメントを再インデックス中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklistTitle": "プロセスを再インデックス中", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails": "このインデックスは現在閉じています。アップグレードアシスタントが開き、再インデックスを実行してからインデックスを閉じます。 {reindexingMayTakeLongerEmph}。詳細については {docs} をご覧ください。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails.reindexingTakesLongerEmphasis": "再インデックスには通常よりも時間がかかることがあります", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutTitle": "インデックスが閉じました", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.openAndCloseDocumentation": "ドキュメンテーション", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.customTypeNameWarningDetail": "マッピングタイプは8.0ではサポートされていません。アプリケーションコードまたはスクリプトが{mappingType}に依存していないことを確認してください。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.customTypeNameWarningTitle": "マッピングタイプ{mappingType}を{defaultType}で置き換えます", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.deprecatedIndexSettingsWarningDetail": "次の廃止予定のインデックス設定が検出されました。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 847bebb961fe6..fe9cf6e4449af 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25615,10 +25615,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.readonlyStepTitle": "正在将旧索引设置为只读", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.reindexingDocumentsStepTitle": "正在重新索引文档", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklistTitle": "重新索引过程", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails": "此索引当前已关闭。升级助手将打开索引,重新索引,然后关闭索引。{reindexingMayTakeLongerEmph}。请参阅文档{docs}以了解更多信息。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails.reindexingTakesLongerEmphasis": "重新索引可能比通常花费更多的时间", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutTitle": "索引已关闭", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.openAndCloseDocumentation": "文档", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.customTypeNameWarningDetail": "映射类型在 8.0 中不再受支持。确保没有应用程序代码或脚本依赖 {mappingType}。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.customTypeNameWarningTitle": "将映射类型 {mappingType} 替换为 {defaultType}", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.warningsStep.deprecatedIndexSettingsWarningDetail": "检测到以下弃用的索引设置:", diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx index 3ba0428f8bb33..19d61b3a8afa9 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx @@ -61,12 +61,11 @@ const buttonLabel = (status?: ReindexStatus) => { * Displays a flyout that shows the current reindexing status for a given index. */ export const ChecklistFlyoutStep: React.FunctionComponent<{ - renderGlobalCallouts: () => React.ReactNode; closeFlyout: () => void; reindexState: ReindexState; startReindex: () => void; cancelReindex: () => void; -}> = ({ closeFlyout, reindexState, startReindex, cancelReindex, renderGlobalCallouts }) => { +}> = ({ closeFlyout, reindexState, startReindex, cancelReindex }) => { const { loadingState, status, hasRequiredPrivileges } = reindexState; const loading = loadingState === LoadingState.Loading || status === ReindexStatus.inProgress; const isCompleted = status === ReindexStatus.completed; @@ -116,7 +115,6 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ )} - {renderGlobalCallouts()} void; } -const getOpenAndCloseIndexDocLink = (docLinks: DocLinksStart) => ( - - {i18n.translate( - 'xpack.upgradeAssistant.checkupTab.reindexing.flyout.openAndCloseDocumentation', - { defaultMessage: 'documentation' } - )} - -); - -const getIndexClosedCallout = (docLinks: DocLinksStart) => ( - <> - -

- - {i18n.translate( - 'xpack.upgradeAssistant.checkupTab.reindexing.flyout.indexClosedCallout.calloutDetails.reindexingTakesLongerEmphasis', - { defaultMessage: 'Reindexing may take longer than usual' } - )} - - ), - }} - /> -

-
- - -); - export const ReindexFlyout: React.FunctionComponent = ({ reindexState, startReindex, @@ -82,12 +34,8 @@ export const ReindexFlyout: React.FunctionComponent = ({ deprecation, }) => { const { status, reindexWarnings } = reindexState; - const { index, correctiveAction } = deprecation; - const { - services: { - core: { docLinks }, - }, - } = useAppContext(); + const { index } = deprecation; + // If there are any warnings and we haven't started reindexing, show the warnings step first. const [currentFlyoutStep, setCurrentFlyoutStep] = useState( reindexWarnings && reindexWarnings.length > 0 && status === undefined @@ -97,16 +45,10 @@ export const ReindexFlyout: React.FunctionComponent = ({ let flyoutContents: React.ReactNode; - const globalCallout = - (correctiveAction as ReindexAction).blockerForReindexing === 'index-closed' && - reindexState.status !== ReindexStatus.completed - ? getIndexClosedCallout(docLinks) - : undefined; switch (currentFlyoutStep) { case ReindexFlyoutStep.reindexWarnings: flyoutContents = ( globalCallout} closeFlyout={closeFlyout} warnings={reindexState.reindexWarnings!} advanceNextStep={() => setCurrentFlyoutStep(ReindexFlyoutStep.checklist)} @@ -116,7 +58,6 @@ export const ReindexFlyout: React.FunctionComponent = ({ case ReindexFlyoutStep.checklist: flyoutContents = ( globalCallout} closeFlyout={closeFlyout} reindexState={reindexState} startReindex={startReindex} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx index 8078d495c4009..0596c692a9f38 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx @@ -41,7 +41,6 @@ const warningToComponentMap: { export const idForWarning = (id: number) => `reindexWarning-${id}`; interface WarningsConfirmationFlyoutProps { - renderGlobalCallouts: () => React.ReactNode; closeFlyout: () => void; warnings: ReindexWarning[]; advanceNextStep: () => void; @@ -53,7 +52,6 @@ interface WarningsConfirmationFlyoutProps { */ export const WarningsFlyoutStep: React.FunctionComponent = ({ warnings, - renderGlobalCallouts, closeFlyout, advanceNextStep, }) => { @@ -88,8 +86,6 @@ export const WarningsFlyoutStep: React.FunctionComponent - {renderGlobalCallouts()} - Date: Fri, 15 Oct 2021 10:41:18 -0700 Subject: [PATCH 69/93] Add LevelIconTips to be more explicit about the difference between critical and warning issues. (#115121) --- .../fix_issues_step/fix_issues_step.tsx | 2 +- .../components/shared/deprecation_count.tsx | 32 +++++++++++++++---- .../application/components/shared/index.ts | 1 + .../components/shared/level_info_tip.tsx | 27 ++++++++++++++++ 4 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/level_info_tip.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx index b061ab5ea2d4d..590bfac96770d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx @@ -70,7 +70,7 @@ export const getFixIssuesStep = ({

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx index 3312508a87073..32d214f0d80f2 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_count.tsx @@ -6,10 +6,11 @@ */ import React, { FunctionComponent } from 'react'; - import { EuiFlexGroup, EuiFlexItem, EuiHealth } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { LevelInfoTip } from './level_info_tip'; + const i18nTexts = { getCriticalStatusLabel: (count: number) => i18n.translate('xpack.upgradeAssistant.deprecationCount.criticalStatusLabel', { @@ -39,14 +40,31 @@ export const DeprecationCount: FunctionComponent = ({ return ( - - {i18nTexts.getCriticalStatusLabel(totalCriticalDeprecations)} - + + + + {i18nTexts.getCriticalStatusLabel(totalCriticalDeprecations)} + + + + + + + + - - {i18nTexts.getWarningStatusLabel(totalWarningDeprecations)} - + + + + {i18nTexts.getWarningStatusLabel(totalWarningDeprecations)} + + + + + + + ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts index ef7916f6e8d17..0efc91035001a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts @@ -9,3 +9,4 @@ export { NoDeprecationsPrompt } from './no_deprecations'; export { DeprecationCount } from './deprecation_count'; export { DeprecationBadge } from './deprecation_badge'; export { DeprecationsPageLoadingError } from './deprecations_page_loading_error'; +export { LevelInfoTip } from './level_info_tip'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/level_info_tip.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/level_info_tip.tsx new file mode 100644 index 0000000000000..d3600a7290b4e --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/level_info_tip.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiIconTip } from '@elastic/eui'; + +const i18nTexts = { + critical: i18n.translate('xpack.upgradeAssistant.levelInfoTip.criticalLabel', { + defaultMessage: 'Critical issues must be resolved before you upgrade', + }), + warning: i18n.translate('xpack.upgradeAssistant.levelInfoTip.warningLabel', { + defaultMessage: 'Warning issues can be ignored at your discretion', + }), +}; + +interface Props { + level: 'critical' | 'warning'; +} + +export const LevelInfoTip: FunctionComponent = ({ level }) => { + return ; +}; From a2ed6965ca0a0096998b6c203fda7d7d3d5f9661 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Fri, 15 Oct 2021 15:56:06 -0700 Subject: [PATCH 70/93] Extract common DeprecationFlyoutLearnMoreLink component and change wording to 'Learn more'. (#115117) --- .../default_deprecation_flyout.test.ts | 5 +++- .../index_settings_deprecation_flyout.test.ts | 11 ++++++--- .../ml_snapshots_deprecation_flyout.test.ts | 9 ++++--- .../deprecation_types/default/flyout.tsx | 13 ++-------- .../index_settings/flyout.tsx | 13 ++-------- .../deprecation_types/ml_snapshots/flyout.tsx | 14 +++-------- .../deprecation_details_flyout.tsx | 14 ++--------- .../deprecation_flyout_learn_more_link.tsx | 24 +++++++++++++++++++ .../application/components/shared/index.ts | 1 + 9 files changed, 52 insertions(+), 52 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_flyout_learn_more_link.tsx diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts index 1975d0abaf11d..fdd8a1c993937 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts @@ -35,7 +35,7 @@ describe('Default deprecation flyout', () => { testBed.component.update(); }); - it('renders a flyout with deprecation details', async () => { + test('renders a flyout with deprecation details', async () => { const multiFieldsDeprecation = esDeprecationsMockResponse.deprecations[2]; const { actions, find, exists } = testBed; @@ -45,6 +45,9 @@ describe('Default deprecation flyout', () => { expect(find('defaultDeprecationDetails.flyoutTitle').text()).toContain( multiFieldsDeprecation.message ); + expect(find('defaultDeprecationDetails.documentationLink').props().href).toBe( + multiFieldsDeprecation.url + ); expect(find('defaultDeprecationDetails.flyoutDescription').text()).toContain( multiFieldsDeprecation.index ); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts index 145cea24dde8b..f62d24081ed56 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts @@ -33,16 +33,21 @@ describe('Index settings deprecation flyout', () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); }); - const { find, exists, actions, component } = testBed; - + const { actions, component } = testBed; component.update(); - await actions.table.clickDeprecationRowAt('indexSetting', 0); + }); + + test('renders a flyout with deprecation details', async () => { + const { find, exists } = testBed; expect(exists('indexSettingsDetails')).toBe(true); expect(find('indexSettingsDetails.flyoutTitle').text()).toContain( indexSettingDeprecation.message ); + expect(find('indexSettingsDetails.documentationLink').props().href).toBe( + indexSettingDeprecation.url + ); expect(exists('removeSettingsPrompt')).toBe(true); }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts index 6bcb3fa95985c..b24cd5a69a28e 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts @@ -35,16 +35,19 @@ describe('Machine learning deprecation flyout', () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); }); - const { find, exists, actions, component } = testBed; - + const { actions, component } = testBed; component.update(); - await actions.table.clickDeprecationRowAt('mlSnapshot', 0); + }); + + test('renders a flyout with deprecation details', async () => { + const { find, exists } = testBed; expect(exists('mlSnapshotDetails')).toBe(true); expect(find('mlSnapshotDetails.flyoutTitle').text()).toContain( 'Upgrade or delete model snapshot' ); + expect(find('mlSnapshotDetails.documentationLink').props().href).toBe(mlDeprecation.url); }); describe('upgrade snapshots', () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx index c436d585db9ae..6ec05b0c4fc99 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/default/flyout.tsx @@ -17,12 +17,11 @@ import { EuiTitle, EuiText, EuiTextColor, - EuiLink, EuiSpacer, } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; -import { DeprecationBadge } from '../../../shared'; +import { DeprecationFlyoutLearnMoreLink, DeprecationBadge } from '../../../shared'; export interface DefaultDeprecationFlyoutProps { deprecation: EnrichedDeprecationInfo; @@ -40,12 +39,6 @@ const i18nTexts = { }, } ), - learnMoreLinkLabel: i18n.translate( - 'xpack.upgradeAssistant.esDeprecations.deprecationDetailsFlyout.learnMoreLinkLabel', - { - defaultMessage: 'Learn more about this deprecation', - } - ), closeButtonLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.deprecationDetailsFlyout.closeButtonLabel', { @@ -80,9 +73,7 @@ export const DefaultDeprecationFlyout = ({

{details}

- - {i18nTexts.learnMoreLinkLabel} - +

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx index 3c19268a293f0..d0aac8ee922f7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx @@ -19,7 +19,6 @@ import { EuiTitle, EuiText, EuiTextColor, - EuiLink, EuiSpacer, EuiCallOut, } from '@elastic/eui'; @@ -30,7 +29,7 @@ import { ResponseError, } from '../../../../../../common/types'; import type { Status } from '../../../types'; -import { DeprecationBadge } from '../../../shared'; +import { DeprecationFlyoutLearnMoreLink, DeprecationBadge } from '../../../shared'; export interface RemoveIndexSettingsFlyoutProps { deprecation: EnrichedDeprecationInfo; @@ -53,12 +52,6 @@ const i18nTexts = { }, } ), - learnMoreLinkLabel: i18n.translate( - 'xpack.upgradeAssistant.esDeprecations.removeSettingsFlyout.learnMoreLinkLabel', - { - defaultMessage: 'Learn more about this deprecation', - } - ), removeButtonLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.removeSettingsFlyout.removeButtonLabel', { @@ -146,9 +139,7 @@ export const RemoveIndexSettingsFlyout = ({

{details}

- - {i18nTexts.learnMoreLinkLabel} - +

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index 4e3d77ba72ae8..c4145bf3d4146 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -25,9 +25,9 @@ import { } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; -import { DeprecationBadge } from '../../../shared'; -import { MlSnapshotContext } from './context'; import { useAppContext } from '../../../../app_context'; +import { DeprecationFlyoutLearnMoreLink, DeprecationBadge } from '../../../shared'; +import { MlSnapshotContext } from './context'; import { SnapshotState } from './use_snapshot_state'; export interface FixSnapshotsFlyoutProps extends MlSnapshotContext { @@ -93,12 +93,6 @@ const i18nTexts = { defaultMessage: 'Error upgrading snapshot', } ), - learnMoreLinkLabel: i18n.translate( - 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.learnMoreLinkLabel', - { - defaultMessage: 'Learn more about this deprecation', - } - ), upgradeModeEnabledErrorTitle: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.upgradeModeEnabledErrorTitle', { @@ -229,9 +223,7 @@ export const FixSnapshotsFlyout = ({

{deprecation.details}

- - {i18nTexts.learnMoreLinkLabel} - +

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index 577354b35fa4e..5d10350caad9e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -20,12 +20,11 @@ import { EuiTitle, EuiText, EuiCallOut, - EuiLink, EuiSpacer, } from '@elastic/eui'; +import { DeprecationFlyoutLearnMoreLink, DeprecationBadge } from '../shared'; import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; -import { DeprecationBadge } from '../shared'; import './_deprecation_details_flyout.scss'; @@ -37,12 +36,6 @@ export interface DeprecationDetailsFlyoutProps { } const i18nTexts = { - learnMoreLinkLabel: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.flyout.learnMoreLinkLabel', - { - defaultMessage: 'Learn more about this deprecation', - } - ), closeButtonLabel: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecations.flyout.closeButtonLabel', { @@ -162,12 +155,9 @@ export const DeprecationDetailsFlyout = ({

{message}

- {documentationUrl && (

- - {i18nTexts.learnMoreLinkLabel} - +

)}
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_flyout_learn_more_link.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_flyout_learn_more_link.tsx new file mode 100644 index 0000000000000..da8c83597f7e2 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_flyout_learn_more_link.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiLink } from '@elastic/eui'; + +interface Props { + documentationUrl?: string; +} + +export const DeprecationFlyoutLearnMoreLink = ({ documentationUrl }: Props) => { + return ( + + {i18n.translate('xpack.upgradeAssistant.deprecationFlyout.learnMoreLinkLabel', { + defaultMessage: 'Learn more', + })} + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts index 0efc91035001a..34496e1e8eb55 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts @@ -9,4 +9,5 @@ export { NoDeprecationsPrompt } from './no_deprecations'; export { DeprecationCount } from './deprecation_count'; export { DeprecationBadge } from './deprecation_badge'; export { DeprecationsPageLoadingError } from './deprecations_page_loading_error'; +export { DeprecationFlyoutLearnMoreLink } from './deprecation_flyout_learn_more_link'; export { LevelInfoTip } from './level_info_tip'; From 6ca676c6a3cc8926622fdc0f5f15a7a575b8a807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Mon, 18 Oct 2021 14:35:11 +0200 Subject: [PATCH 71/93] [Upgrade Assistant] Reindexing cancellation (#114636) * [Upgrade Assistant] Updated the reindexing cancellation to look less like an error * [Upgrade Assistant] Fixed an i18n issue and updated a jest snapshot * [Upgrade Assistant] Updated cancelled reindexing state with a unified label and cross icon * [Upgrade Assistant] Fixed snapshot test * [Upgrade Assistant] Updated spacing to the reindex cancel button Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../reindex/flyout/_step_progress.scss | 2 +- .../reindex/flyout/checklist_step.tsx | 7 ++ .../reindex/flyout/progress.test.tsx | 22 ++-- .../reindex/flyout/progress.tsx | 81 +++++++------- .../reindex/flyout/step_progress.tsx | 6 +- .../reindex/resolution_table_cell.tsx | 13 +-- .../reindex/use_reindex_state.tsx | 105 +++++++++++------- .../public/application/components/types.ts | 7 ++ 8 files changed, 131 insertions(+), 112 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_step_progress.scss b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_step_progress.scss index a754541c2ff83..4d8ee5def30eb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_step_progress.scss +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/_step_progress.scss @@ -18,7 +18,7 @@ $stepStatusToCallOutColor: ( failed: 'danger', complete: 'success', paused: 'warning', - cancelled: 'danger', + cancelled: 'warning', ); .upgStepProgress__status--circle { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx index 19d61b3a8afa9..5e2f0d26447b2 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx @@ -47,6 +47,13 @@ const buttonLabel = (status?: ReindexStatus) => { defaultMessage="Resume" /> ); + case ReindexStatus.cancelled: + return ( + + ); default: return ( { }, Object { "status": "incomplete", - "title": - - - - , + "title": , }, Object { "status": "incomplete", diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx index afeac303284f1..f5dc04783b031 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx @@ -7,18 +7,11 @@ import React from 'react'; -import { - EuiButtonEmpty, - EuiCallOut, - EuiFlexGroup, - EuiFlexItem, - EuiText, - EuiTitle, -} from '@elastic/eui'; +import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink, EuiText, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { ReindexStatus, ReindexStep } from '../../../../../../../common/types'; -import { LoadingState } from '../../../../types'; +import { CancelLoadingState } from '../../../../types'; import type { ReindexState } from '../use_reindex_state'; import { StepProgress, StepProgressStep } from './step_progress'; import { getReindexProgressLabel } from '../../../../../lib/utils'; @@ -40,13 +33,27 @@ const PausedCallout = () => ( /> ); -const CancelReindexingDocumentsButton: React.FunctionComponent<{ +const ReindexingDocumentsStepTitle: React.FunctionComponent<{ reindexState: ReindexState; cancelReindex: () => void; }> = ({ reindexState: { lastCompletedStep, status, cancelLoadingState }, cancelReindex }) => { + if (status === ReindexStatus.cancelled) { + return ( + <> + + + ); + } + const showCancelLink = + status === ReindexStatus.inProgress && lastCompletedStep === ReindexStep.reindexStarted; + let cancelText: React.ReactNode; switch (cancelLoadingState) { - case LoadingState.Loading: + case CancelLoadingState.Requested: + case CancelLoadingState.Loading: cancelText = ( ); break; - case LoadingState.Success: + case CancelLoadingState.Success: cancelText = ( ); break; - case LoadingState.Error: + case CancelLoadingState.Error: cancelText = ( - {cancelText} - + + + + + {showCancelLink && ( + + + {cancelText} + + + )} + ); }; @@ -145,22 +159,7 @@ export const ReindexProgress: React.FunctionComponent<{ // The reindexing step is special because it generally lasts longer and can be cancelled mid-flight const reindexingDocsStep = { - title: ( - - - - - {(lastCompletedStep === ReindexStep.newIndexCreated || - lastCompletedStep === ReindexStep.reindexStarted) && ( - - - - )} - - ), + title: , } as StepProgressStep; if ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx index d5947426aee3d..2de21ad86f839 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx @@ -56,11 +56,7 @@ const Step: React.FunctionComponent = ({ }) => { const titleClassName = classNames('upgStepProgress__title', { // eslint-disable-next-line @typescript-eslint/naming-convention - 'upgStepProgress__title--currentStep': - status === 'inProgress' || - status === 'paused' || - status === 'failed' || - status === 'cancelled', + 'upgStepProgress__title--currentStep': status === 'inProgress', }); return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx index 84c6c16d4032a..d743a7d3018dc 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx @@ -55,7 +55,7 @@ const i18nTexts = { reindexCanceledText: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.reindex.reindexCanceledText', { - defaultMessage: 'Reindex canceled', + defaultMessage: 'Reindex cancelled', } ), reindexPausedText: i18n.translate( @@ -154,17 +154,6 @@ export const ReindexResolutionCell: React.FunctionComponent = () => { ); - case ReindexStatus.cancelled: - return ( - - - - - - {i18nTexts.reindexCanceledText} - - - ); } return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index cbeebd00f2bb8..68737d1bbff87 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -13,14 +13,14 @@ import { ReindexStep, ReindexWarning, } from '../../../../../../common/types'; -import { LoadingState } from '../../../types'; +import { CancelLoadingState, LoadingState } from '../../../types'; import { ApiService } from '../../../../lib/api'; const POLL_INTERVAL = 1000; export interface ReindexState { loadingState: LoadingState; - cancelLoadingState?: LoadingState; + cancelLoadingState?: CancelLoadingState; lastCompletedStep?: ReindexStep; status?: ReindexStatus; reindexTaskPercComplete: number | null; @@ -59,8 +59,21 @@ const getReindexState = ( newReindexState.reindexTaskPercComplete = reindexOp.reindexTaskPercComplete; newReindexState.errorMessage = reindexOp.errorMessage; - if (reindexOp.status === ReindexStatus.cancelled) { - newReindexState.cancelLoadingState = LoadingState.Success; + // if reindex cancellation was "requested" or "loading" and the reindex task is now cancelled, + // then reindex cancellation has completed, set it to "success" + if ( + (reindexState.cancelLoadingState === CancelLoadingState.Requested || + reindexState.cancelLoadingState === CancelLoadingState.Loading) && + reindexOp.status === ReindexStatus.cancelled + ) { + newReindexState.cancelLoadingState = CancelLoadingState.Success; + } else if ( + // if reindex cancellation has been requested and the reindex task is still in progress, + // then reindex cancellation has not completed yet, set it to "loading" + reindexState.cancelLoadingState === CancelLoadingState.Requested && + reindexOp.status === ReindexStatus.inProgress + ) { + newReindexState.cancelLoadingState = CancelLoadingState.Loading; } } @@ -90,39 +103,39 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A const { data, error } = await api.getReindexStatus(indexName); if (error) { - setReindexState({ - ...reindexState, - loadingState: LoadingState.Error, - errorMessage: error.message.toString(), - status: ReindexStatus.fetchFailed, + setReindexState((prevValue: ReindexState) => { + return { + ...prevValue, + loadingState: LoadingState.Error, + errorMessage: error.message.toString(), + status: ReindexStatus.fetchFailed, + }; }); return; } - setReindexState(getReindexState(reindexState, data)); + setReindexState((prevValue: ReindexState) => { + return getReindexState(prevValue, data); + }); // Only keep polling if it exists and is in progress. if (data.reindexOp && data.reindexOp.status === ReindexStatus.inProgress) { pollIntervalIdRef.current = setTimeout(updateStatus, POLL_INTERVAL); } - }, [clearPollInterval, api, indexName, reindexState]); + }, [clearPollInterval, api, indexName]); const startReindex = useCallback(async () => { - const currentReindexState = { - ...reindexState, - }; - - setReindexState({ - ...currentReindexState, - // Only reset last completed step if we aren't currently paused - lastCompletedStep: - currentReindexState.status === ReindexStatus.paused - ? currentReindexState.lastCompletedStep - : undefined, - status: ReindexStatus.inProgress, - reindexTaskPercComplete: null, - errorMessage: null, - cancelLoadingState: undefined, + setReindexState((prevValue: ReindexState) => { + return { + ...prevValue, + // Only reset last completed step if we aren't currently paused + lastCompletedStep: + prevValue.status === ReindexStatus.paused ? prevValue.lastCompletedStep : undefined, + status: ReindexStatus.inProgress, + reindexTaskPercComplete: null, + errorMessage: null, + cancelLoadingState: undefined, + }; }); api.sendReindexTelemetryData({ start: true }); @@ -130,37 +143,45 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A const { data: reindexOp, error } = await api.startReindexTask(indexName); if (error) { - setReindexState({ - ...reindexState, - loadingState: LoadingState.Error, - errorMessage: error.message.toString(), - status: ReindexStatus.failed, + setReindexState((prevValue: ReindexState) => { + return { + ...prevValue, + loadingState: LoadingState.Error, + errorMessage: error.message.toString(), + status: ReindexStatus.failed, + }; }); return; } - setReindexState(getReindexState(reindexState, { reindexOp })); + setReindexState((prevValue: ReindexState) => { + return getReindexState(prevValue, { reindexOp }); + }); updateStatus(); - }, [api, indexName, reindexState, updateStatus]); + }, [api, indexName, updateStatus]); const cancelReindex = useCallback(async () => { api.sendReindexTelemetryData({ stop: true }); - const { error } = await api.cancelReindexTask(indexName); - - setReindexState({ - ...reindexState, - cancelLoadingState: LoadingState.Loading, + setReindexState((prevValue: ReindexState) => { + return { + ...prevValue, + cancelLoadingState: CancelLoadingState.Requested, + }; }); + const { error } = await api.cancelReindexTask(indexName); + if (error) { - setReindexState({ - ...reindexState, - cancelLoadingState: LoadingState.Error, + setReindexState((prevValue: ReindexState) => { + return { + ...prevValue, + cancelLoadingState: CancelLoadingState.Error, + }; }); return; } - }, [api, indexName, reindexState]); + }, [api, indexName]); useEffect(() => { isMounted.current = true; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts index 31dd9cf43656d..637c48cc61403 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts @@ -13,6 +13,13 @@ export enum LoadingState { Error, } +export enum CancelLoadingState { + Requested, + Loading, + Success, + Error, +} + export type DeprecationTableColumns = | 'type' | 'index' From 19107ef0a1d2687124d65d6ba53ffcfbe4c09708 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 18 Oct 2021 18:29:27 +0100 Subject: [PATCH 72/93] Fix test errors (#115183) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/es_ui_shared/public/request/use_request.ts | 9 +++++++-- .../deprecation_types/reindex/flyout/step_progress.tsx | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/plugins/es_ui_shared/public/request/use_request.ts b/src/plugins/es_ui_shared/public/request/use_request.ts index 33085bdbf4478..1241d6222a38f 100644 --- a/src/plugins/es_ui_shared/public/request/use_request.ts +++ b/src/plugins/es_ui_shared/public/request/use_request.ts @@ -103,8 +103,13 @@ export const useRequest = ( : serializedResponseData; setData(responseData); } - // Setting isLoading to false also acts as a signal for scheduling the next poll request. - setIsLoading(false); + // There can be situations in which a component that consumes this hook gets unmounted when + // the request returns an error. So before changing the isLoading state, check if the component + // is still mounted. + if (isMounted.current === true) { + // Setting isLoading to false also acts as a signal for scheduling the next poll request. + setIsLoading(false); + } }, [requestBody, httpClient, deserializer, clearPollInterval] ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx index 2de21ad86f839..01b4fe4eb84fc 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/step_progress.tsx @@ -63,7 +63,7 @@ const Step: React.FunctionComponent = ({
-

{title}

+
{title}
{children &&
{children}
}
From 46d5c14487c136394bdae2909aad625834c0bc71 Mon Sep 17 00:00:00 2001 From: Dmitry Borodyansky Date: Mon, 18 Oct 2021 11:37:19 -0700 Subject: [PATCH 73/93] [Upgrade Assistant] Overview page UI clean up (#115258) - Scaling down deprecation issue panel title size to flow with typographic hierarchy. - Removing panel around deprecation logging switch to reduce visual elements. - Using success instead of green color for migration complete message. --- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../components/deprecation_issues_panel.tsx | 3 +- .../overview/fix_logs_step/fix_logs_step.tsx | 29 +++++++------------ .../migrate_system_indices.tsx | 2 +- 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7b8dd06682d33..7e701fb110827 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25234,7 +25234,6 @@ "xpack.upgradeAssistant.overview.observe.observabilityDescription": "使用中のAPIのうち廃止予定のAPIと、更新が必要なアプリケーションを特定できます。", "xpack.upgradeAssistant.overview.pageDescription": "次のバージョンのElastic Stackをお待ちください。", "xpack.upgradeAssistant.overview.pageTitle": "アップグレードアシスタント", - "xpack.upgradeAssistant.overview.toggleTitle": "Elasticsearch廃止予定警告をログに出力", "xpack.upgradeAssistant.overview.upgradeGuideLink": "アップグレードガイドを表示", "xpack.upgradeAssistant.overview.upgradeStepCloudLink": "クラウドでアップグレード", "xpack.upgradeAssistant.overview.upgradeStepDescription": "重要な問題をすべて解決し、アプリケーションの準備を確認した後に、Elastic Stackをアップグレードできます。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index fe9cf6e4449af..95d575a7198b0 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25663,7 +25663,6 @@ "xpack.upgradeAssistant.overview.observe.observabilityDescription": "深入了解正在使用哪些已弃用 API 以及需要更新哪些应用程序。", "xpack.upgradeAssistant.overview.pageDescription": "准备使用下一版 Elastic Stack!", "xpack.upgradeAssistant.overview.pageTitle": "升级助手", - "xpack.upgradeAssistant.overview.toggleTitle": "记录 Elasticsearch 弃用警告", "xpack.upgradeAssistant.overview.upgradeGuideLink": "查看升级指南", "xpack.upgradeAssistant.overview.upgradeStepCloudLink": "在 Cloud 上升级", "xpack.upgradeAssistant.overview.upgradeStepDescription": "解决所有关键问题并确认您的应用程序就绪后,便可以升级 Elastic Stack。", diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx index 084e4528694dd..8c42e71c0ef2b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/components/deprecation_issues_panel.tsx @@ -73,9 +73,10 @@ export const DeprecationIssuesPanel = (props: Props) => { className="upgDeprecationIssuesPanel" layout="horizontal" title={deprecationSource} + titleSize="xs" {...(!hasNoIssues && reactRouterNavigate(history, linkUrl))} > - + {hasError ? ( {errorMessage} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx index 42ab75a3ee3f4..aeba230a5b27b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx @@ -8,7 +8,7 @@ import React, { FunctionComponent, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiText, EuiSpacer, EuiPanel, EuiLink, EuiCallOut, EuiCode } from '@elastic/eui'; +import { EuiText, EuiSpacer, EuiLink, EuiCallOut, EuiCode } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import { useAppContext } from '../../../app_context'; @@ -25,9 +25,6 @@ const i18nTexts = { identifyStepTitle: i18n.translate('xpack.upgradeAssistant.overview.identifyStepTitle', { defaultMessage: 'Identify deprecated API use and update your applications', }), - toggleTitle: i18n.translate('xpack.upgradeAssistant.overview.toggleTitle', { - defaultMessage: 'Log Elasticsearch deprecation issues', - }), analyzeTitle: i18n.translate('xpack.upgradeAssistant.overview.analyzeTitle', { defaultMessage: 'Analyze deprecation logs', }), @@ -140,21 +137,15 @@ const FixLogsStep: FunctionComponent = ({ return ( <> - -

{i18nTexts.toggleTitle}

-
- - - - + {onlyDeprecationLogWritingEnabled && ( <> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx index ab370c99bfc58..75806f43bb19e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx @@ -118,7 +118,7 @@ const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) = - +

{i18nTexts.noMigrationNeeded}

From d7a654f1d705235af299afa82833dc786c77748e Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Mon, 18 Oct 2021 15:07:59 -0700 Subject: [PATCH 74/93] Revert "Revert "[Upgrade Assistant] Refactor telemetry (#112177)" (#113665)" (#114804) This reverts commit c385d498874d4ca34f454e3cb9ad9e4c0e3219ae. * Add migration to remove obsolete attributes from telemetry saved object. * Refactor UA telemetry constants by extracting it from common/types. --- .../schema/xpack_plugins.json | 38 ---- x-pack/plugins/upgrade_assistant/README.md | 27 ++- .../helpers/setup_environment.tsx | 2 +- .../upgrade_assistant/common/constants.ts | 3 + .../plugins/upgrade_assistant/common/types.ts | 31 --- .../index_settings/flyout.tsx | 16 +- .../deprecation_types/ml_snapshots/flyout.tsx | 8 + .../checklist_step.test.tsx.snap | 4 +- .../reindex/flyout/checklist_step.tsx | 22 ++- .../deprecation_types/reindex/table_row.tsx | 21 +- .../reindex/use_reindex_state.tsx | 4 - .../es_deprecations/es_deprecations.tsx | 22 +-- .../deprecation_details_flyout.tsx | 11 +- .../kibana_deprecations.tsx | 13 +- .../overview/backup_step/cloud_backup.tsx | 8 +- .../overview/backup_step/on_prem_backup.tsx | 11 +- .../deprecations_count_checkpoint.tsx | 5 +- .../overview/fix_logs_step/external_links.tsx | 27 ++- .../components/overview/overview.tsx | 13 +- .../public/application/lib/api.ts | 16 -- .../public/application/lib/ui_metric.ts | 49 +++++ .../upgrade_assistant/public/plugin.ts | 78 ++++---- .../plugins/upgrade_assistant/public/types.ts | 3 +- .../lib/telemetry/es_ui_open_apis.test.ts | 48 ----- .../server/lib/telemetry/es_ui_open_apis.ts | 57 ------ .../lib/telemetry/es_ui_reindex_apis.test.ts | 52 ----- .../lib/telemetry/es_ui_reindex_apis.ts | 63 ------ .../lib/telemetry/usage_collector.test.ts | 31 --- .../server/lib/telemetry/usage_collector.ts | 113 +---------- .../upgrade_assistant/server/plugin.ts | 3 +- .../server/routes/register_routes.ts | 2 - .../server/routes/telemetry.test.ts | 187 ------------------ .../server/routes/telemetry.ts | 64 ------ .../saved_object_types/migrations/index.ts | 8 + .../telemetry_saved_object_migrations.test.ts | 41 ++++ .../telemetry_saved_object_migrations.ts | 40 ++++ .../telemetry_saved_object_type.ts | 42 +--- 37 files changed, 338 insertions(+), 845 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts delete mode 100644 x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/index.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.test.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.ts diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index b3ca5f17634d5..ab1b77587bf78 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -7329,44 +7329,6 @@ } } } - }, - "ui_open": { - "properties": { - "elasticsearch": { - "type": "long", - "_meta": { - "description": "Number of times a user viewed the list of Elasticsearch deprecations." - } - }, - "overview": { - "type": "long", - "_meta": { - "description": "Number of times a user viewed the Overview page." - } - }, - "kibana": { - "type": "long", - "_meta": { - "description": "Number of times a user viewed the list of Kibana deprecations" - } - } - } - }, - "ui_reindex": { - "properties": { - "close": { - "type": "long" - }, - "open": { - "type": "long" - }, - "start": { - "type": "long" - }, - "stop": { - "type": "long" - } - } } } }, diff --git a/x-pack/plugins/upgrade_assistant/README.md b/x-pack/plugins/upgrade_assistant/README.md index 255eb94a0318c..6570e7f8d7617 100644 --- a/x-pack/plugins/upgrade_assistant/README.md +++ b/x-pack/plugins/upgrade_assistant/README.md @@ -226,4 +226,29 @@ This is a non-exhaustive list of different error scenarios in Upgrade Assistant. - **Error updating deprecation logging status.** Mock a `404` status code to `PUT /api/upgrade_assistant/deprecation_logging`. Alternatively, edit [this line](https://github.com/elastic/kibana/blob/545c1420c285af8f5eee56f414bd6eca735aea11/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts#L77) locally and replace `deprecation_logging` with `fake_deprecation_logging`. - **Unauthorized error fetching ES deprecations.** Mock a `403` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 403 }` - **Partially upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": false } }` -- **Upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": true } }` \ No newline at end of file +- **Upgraded error fetching ES deprecations.** Mock a `426` status code to `GET /api/upgrade_assistant/es_deprecations` with the response payload: `{ "statusCode": 426, "attributes": { "allNodesUpgraded": true } }` + +### Telemetry + +The Upgrade Assistant tracks several triggered events in the UI, using Kibana Usage Collection service's [UI counters](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#ui-counters). + +**Overview page** +- Component loaded +- Click event for "Create snapshot" button +- Click event for "View deprecation logs in Observability" link +- Click event for "Analyze logs in Discover" link +- Click event for "Reset counter" button + +**ES deprecations page** +- Component loaded +- Click events for starting and stopping reindex tasks +- Click events for upgrading or deleting a Machine Learning snapshot +- Click event for deleting a deprecated index setting + +**Kibana deprecations page** +- Component loaded +- Click event for "Quick resolve" button + +In addition to UI counters, the Upgrade Assistant has a [custom usage collector](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#custom-collector). It currently is only responsible for tracking whether the user has deprecation logging enabled or not. + +For testing instructions, refer to the [Kibana Usage Collection service README](https://github.com/elastic/kibana/blob/master/src/plugins/usage_collection/README.mdx#testing). \ No newline at end of file diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx index 88beb138d58c7..8e08ab380ceaf 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx @@ -12,8 +12,8 @@ import { merge } from 'lodash'; // @ts-ignore import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import { MAJOR_VERSION } from '../../../common/constants'; import { HttpSetup } from 'src/core/public'; +import { MAJOR_VERSION } from '../../../common/constants'; import { AuthorizationContext, Authorization, Privileges } from '../../../public/shared_imports'; import { AppContextProvider } from '../../../public/application/app_context'; diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index 0b0a5b57397e0..9f67786c85bab 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -24,6 +24,9 @@ export const indexSettingDeprecations = { export const API_BASE_PATH = '/api/upgrade_assistant'; +// Telemetry constants +export const UPGRADE_ASSISTANT_TELEMETRY = 'upgrade-assistant-telemetry'; + /** * This is the repository where Cloud stores its backup snapshots. */ diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 1017ba071ee24..ac4cd62aa2bea 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -123,8 +123,6 @@ export interface ReindexWarning { } // Telemetry types -export const UPGRADE_ASSISTANT_TYPE = 'upgrade-assistant-telemetry'; -export const UPGRADE_ASSISTANT_DOC_ID = 'upgrade-assistant-telemetry'; export type UIOpenOption = 'overview' | 'elasticsearch' | 'kibana'; export type UIReindexOption = 'close' | 'open' | 'start' | 'stop'; @@ -141,32 +139,7 @@ export interface UIReindex { stop: boolean; } -export interface UpgradeAssistantTelemetrySavedObject { - ui_open: { - overview: number; - elasticsearch: number; - kibana: number; - }; - ui_reindex: { - close: number; - open: number; - start: number; - stop: number; - }; -} - export interface UpgradeAssistantTelemetry { - ui_open: { - overview: number; - elasticsearch: number; - kibana: number; - }; - ui_reindex: { - close: number; - open: number; - start: number; - stop: number; - }; features: { deprecation_logging: { enabled: boolean; @@ -174,10 +147,6 @@ export interface UpgradeAssistantTelemetry { }; } -export interface UpgradeAssistantTelemetrySavedObjectAttributes { - [key: string]: any; -} - export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; export interface DeprecationInfo { level: MIGRATION_DEPRECATION_LEVEL; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx index d0aac8ee922f7..a6add8cccdd2d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/flyout.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButton, EuiButtonEmpty, @@ -28,6 +29,7 @@ import { IndexSettingAction, ResponseError, } from '../../../../../../common/types'; +import { uiMetricService, UIM_INDEX_SETTINGS_DELETE_CLICK } from '../../../../lib/ui_metric'; import type { Status } from '../../../types'; import { DeprecationFlyoutLearnMoreLink, DeprecationBadge } from '../../../shared'; @@ -104,6 +106,11 @@ export const RemoveIndexSettingsFlyout = ({ // Flag used to hide certain parts of the UI if the deprecation has been resolved or is in progress const isResolvable = ['idle', 'error'].includes(statusType); + const onRemoveSettings = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_INDEX_SETTINGS_DELETE_CLICK); + removeIndexSettings(index!, (correctiveAction as IndexSettingAction).deprecatedSettings); + }, [correctiveAction, index, removeIndexSettings]); + return ( <> @@ -185,12 +192,7 @@ export const RemoveIndexSettingsFlyout = ({ fill data-test-subj="deleteSettingsButton" color="danger" - onClick={() => - removeIndexSettings( - index!, - (correctiveAction as IndexSettingAction).deprecatedSettings - ) - } + onClick={onRemoveSettings} > {statusType === 'error' ? i18nTexts.retryRemoveButtonLabel diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx index c4145bf3d4146..a5830cf1ca655 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/flyout.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButton, @@ -25,6 +26,11 @@ import { } from '@elastic/eui'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; +import { + uiMetricService, + UIM_ML_SNAPSHOT_UPGRADE_CLICK, + UIM_ML_SNAPSHOT_DELETE_CLICK, +} from '../../../../lib/ui_metric'; import { useAppContext } from '../../../../app_context'; import { DeprecationFlyoutLearnMoreLink, DeprecationBadge } from '../../../shared'; import { MlSnapshotContext } from './context'; @@ -167,11 +173,13 @@ export const FixSnapshotsFlyout = ({ const isResolved = snapshotState.status === 'complete'; const onUpgradeSnapshot = () => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_ML_SNAPSHOT_UPGRADE_CLICK); upgradeSnapshot(); closeFlyout(); }; const onDeleteSnapshot = () => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_ML_SNAPSHOT_DELETE_CLICK); deleteSnapshot(); closeFlyout(); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index be84bbf143ab3..ff2559ecd8302 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -31,7 +31,7 @@ exports[`ChecklistFlyout renders 1`] = `
{ + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_START_CLICK); + startReindex(); + }, [startReindex]); + + const onStopReindex = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_STOP_CLICK); + cancelReindex(); + }, [cancelReindex]); + return ( @@ -148,7 +164,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{

- +
@@ -166,7 +182,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ fill color={status === ReindexStatus.paused ? 'warning' : 'primary'} iconType={status === ReindexStatus.paused ? 'play' : undefined} - onClick={startReindex} + onClick={onStartReindex} isLoading={loading} disabled={loading || !hasRequiredPrivileges} data-test-subj="startReindexingButton" diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx index c2a14ca5be858..1059720e66a59 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/table_row.tsx @@ -7,9 +7,15 @@ import React, { useState, useEffect, useCallback } from 'react'; import { EuiTableRowCell } from '@elastic/eui'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GlobalFlyout } from '../../../../../shared_imports'; import { useAppContext } from '../../../../app_context'; +import { + uiMetricService, + UIM_REINDEX_CLOSE_FLYOUT_CLICK, + UIM_REINDEX_OPEN_FLYOUT_CLICK, +} from '../../../../lib/ui_metric'; import { DeprecationTableColumns } from '../../../types'; import { EsDeprecationsTableCells } from '../../es_deprecations_table_cells'; import { ReindexResolutionCell } from './resolution_table_cell'; @@ -29,9 +35,6 @@ const ReindexTableRowCells: React.FunctionComponent = ({ }) => { const [showFlyout, setShowFlyout] = useState(false); const reindexState = useReindexContext(); - const { - services: { api }, - } = useAppContext(); const { addContent: addContentToGlobalFlyout, removeContent: removeContentFromGlobalFlyout } = useGlobalFlyout(); @@ -39,8 +42,8 @@ const ReindexTableRowCells: React.FunctionComponent = ({ const closeFlyout = useCallback(async () => { removeContentFromGlobalFlyout('reindexFlyout'); setShowFlyout(false); - await api.sendReindexTelemetryData({ close: true }); - }, [api, removeContentFromGlobalFlyout]); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_CLOSE_FLYOUT_CLICK); + }, [removeContentFromGlobalFlyout]); useEffect(() => { if (showFlyout) { @@ -64,13 +67,9 @@ const ReindexTableRowCells: React.FunctionComponent = ({ useEffect(() => { if (showFlyout) { - async function sendTelemetry() { - await api.sendReindexTelemetryData({ open: true }); - } - - sendTelemetry(); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_OPEN_FLYOUT_CLICK); } - }, [showFlyout, api]); + }, [showFlyout]); return ( <> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index 68737d1bbff87..e3a747e6615b8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -138,8 +138,6 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A }; }); - api.sendReindexTelemetryData({ start: true }); - const { data: reindexOp, error } = await api.startReindexTask(indexName); if (error) { @@ -161,8 +159,6 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A }, [api, indexName, updateStatus]); const cancelReindex = useCallback(async () => { - api.sendReindexTelemetryData({ stop: true }); - setReindexState((prevValue: ReindexState) => { return { ...prevValue, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index c7d157c342c77..7c3394d5a9c0f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -12,10 +12,12 @@ import { EuiPageHeader, EuiSpacer, EuiPageContent, EuiLink } from '@elastic/eui' import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { DocLinksStart } from 'kibana/public'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo } from '../../../../common/types'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; +import { uiMetricService, UIM_ES_DEPRECATIONS_PAGE_LOAD } from '../../lib/ui_metric'; import { getEsDeprecationError } from '../../lib/get_es_deprecation_error'; import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { EsDeprecationsTable } from './es_deprecations_table'; @@ -82,13 +84,7 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { }, } = useAppContext(); - const { - data: esDeprecations, - isLoading, - error, - resendRequest, - isInitialRequest, - } = api.useLoadEsDeprecations(); + const { data: esDeprecations, isLoading, error, resendRequest } = api.useLoadEsDeprecations(); const deprecationsCountByLevel: { warningDeprecations: number; @@ -103,16 +99,8 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { }, [breadcrumbs]); useEffect(() => { - if (isLoading === false && isInitialRequest) { - async function sendTelemetryData() { - await api.sendPageTelemetryData({ - elasticsearch: true, - }); - } - - sendTelemetryData(); - } - }, [api, isLoading, isInitialRequest]); + uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_ES_DEPRECATIONS_PAGE_LOAD); + }, []); if (error) { return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index 5d10350caad9e..041e617d2a020 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -5,9 +5,10 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiButtonEmpty, @@ -23,6 +24,7 @@ import { EuiSpacer, } from '@elastic/eui'; +import { uiMetricService, UIM_KIBANA_QUICK_RESOLVE_CLICK } from '../../lib/ui_metric'; import { DeprecationFlyoutLearnMoreLink, DeprecationBadge } from '../shared'; import type { DeprecationResolutionState, KibanaDeprecationDetails } from './kibana_deprecations'; @@ -127,6 +129,11 @@ export const DeprecationDetailsFlyout = ({ const isCurrent = deprecationResolutionState?.id === deprecation.id; const isResolved = isCurrent && deprecationResolutionState?.resolveDeprecationStatus === 'ok'; + const onResolveDeprecation = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_KIBANA_QUICK_RESOLVE_CLICK); + resolveDeprecation(deprecation); + }, [deprecation, resolveDeprecation]); + return ( <> @@ -227,7 +234,7 @@ export const DeprecationDetailsFlyout = ({ resolveDeprecation(deprecation)} + onClick={onResolveDeprecation} isLoading={Boolean( deprecationResolutionState?.resolveDeprecationStatus === 'in_progress' )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 013f59a7dcf56..22a67b227fd8c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -11,10 +11,12 @@ import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE } from '@kbn/analytics'; import type { DomainDeprecationDetails } from 'kibana/public'; import { SectionLoading, GlobalFlyout } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; +import { uiMetricService, UIM_KIBANA_DEPRECATIONS_PAGE_LOAD } from '../../lib/ui_metric'; import { DeprecationsPageLoadingError, NoDeprecationsPrompt, DeprecationCount } from '../shared'; import { KibanaDeprecationsTable } from './kibana_deprecations_table'; import { @@ -116,7 +118,6 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) services: { core: { deprecations }, breadcrumbs, - api, }, } = useAppContext(); @@ -225,14 +226,8 @@ export const KibanaDeprecations = withRouter(({ history }: RouteComponentProps) ]); useEffect(() => { - async function sendTelemetryData() { - await api.sendPageTelemetryData({ - kibana: true, - }); - } - - sendTelemetryData(); - }, [api]); + uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_KIBANA_DEPRECATIONS_PAGE_LOAD); + }, []); useEffect(() => { breadcrumbs.setBreadcrumbs('kibanaDeprecations'); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx index 55a6ee8e5c73f..4ab860a0bf6a7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/cloud_backup.tsx @@ -9,6 +9,7 @@ import React, { useEffect } from 'react'; import moment from 'moment-timezone'; import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiLoadingContent, EuiFlexGroup, @@ -21,6 +22,7 @@ import { } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; +import { uiMetricService, UIM_BACKUP_DATA_CLOUD_CLICK } from '../../../lib/ui_metric'; interface Props { cloudSnapshotsUrl: string; @@ -128,11 +130,13 @@ export const CloudBackup: React.FunctionComponent = ({ return ( <> {statusMessage} - - + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_BACKUP_DATA_CLOUD_CLICK); + }} data-test-subj="cloudSnapshotsLink" target="_blank" iconType="popout" diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx index 2e2e2bd5ce48e..69100b36db7eb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx @@ -8,9 +8,11 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; import { useAppContext } from '../../../app_context'; +import { uiMetricService, UIM_BACKUP_DATA_ON_PREM_CLICK } from '../../../lib/ui_metric'; const SnapshotRestoreAppLink: React.FunctionComponent = () => { const { @@ -22,7 +24,14 @@ const SnapshotRestoreAppLink: React.FunctionComponent = () => { ?.useUrl({ page: 'snapshots' }); return ( - + // eslint-disable-next-line @elastic/eui/href-or-on-click + { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_BACKUP_DATA_ON_PREM_CLICK); + }} + data-test-subj="snapshotRestoreLink" + > ( @@ -90,6 +92,7 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({ } const now = moment().toISOString(); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_RESET_LOGS_COUNTER_CLICK); setCheckpoint(now); }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx index 7d26e4db69713..dec43145ef966 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/external_links.tsx @@ -9,10 +9,17 @@ import { encode } from 'rison-node'; import React, { FunctionComponent, useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EuiLink, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiPanel, EuiText } from '@elastic/eui'; -import { useAppContext } from '../../../app_context'; import { DataPublicPluginStart } from '../../../../shared_imports'; +import { useAppContext } from '../../../app_context'; +import { + uiMetricService, + UIM_OBSERVABILITY_CLICK, + UIM_DISCOVER_CLICK, +} from '../../../lib/ui_metric'; + import { DEPRECATION_LOGS_INDEX_PATTERN, DEPRECATION_LOGS_SOURCE_ID, @@ -83,7 +90,14 @@ const DiscoverAppLink: FunctionComponent = ({ checkpoint }) => { }, [dataService, checkpoint, share.url.locators]); return ( - + // eslint-disable-next-line @elastic/eui/href-or-on-click + { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_DISCOVER_CLICK); + }} + data-test-subj="viewDiscoverLogs" + > = ({ checkpoint }) => { ); return ( - + // eslint-disable-next-line @elastic/eui/href-or-on-click + { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_OBSERVABILITY_CLICK); + }} + data-test-subj="viewObserveLogs" + > { kibanaVersionInfo: { nextMajor }, services: { breadcrumbs, - api, core: { docLinks }, }, plugins: { cloud }, } = useAppContext(); useEffect(() => { - async function sendTelemetryData() { - await api.sendPageTelemetryData({ - overview: true, - }); - } - - sendTelemetryData(); - }, [api]); + uiMetricService.trackUiMetric(METRIC_TYPE.LOADED, UIM_OVERVIEW_PAGE_LOAD); + }, []); useEffect(() => { breadcrumbs.setBreadcrumbs('overview'); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index 3342435a6d46e..8b967d994af9b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -125,14 +125,6 @@ export class ApiService { }); } - public async sendPageTelemetryData(telemetryData: { [tabName: string]: boolean }) { - return await this.sendRequest({ - path: `${API_BASE_PATH}/stats/ui_open`, - method: 'put', - body: JSON.stringify(telemetryData), - }); - } - public useLoadDeprecationLogging() { return this.useRequest<{ isDeprecationLogIndexingEnabled: boolean; @@ -216,14 +208,6 @@ export class ApiService { }); } - public async sendReindexTelemetryData(telemetryData: { [key: string]: boolean }) { - return await this.sendRequest({ - path: `${API_BASE_PATH}/stats/ui_reindex`, - method: 'put', - body: JSON.stringify(telemetryData), - }); - } - public async getReindexStatus(indexName: string) { return await this.sendRequest({ path: `${API_BASE_PATH}/reindex/${indexName}`, diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.ts new file mode 100644 index 0000000000000..394f046a8bafe --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/ui_metric.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { UiCounterMetricType } from '@kbn/analytics'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; + +export const UIM_APP_NAME = 'upgrade_assistant'; +export const UIM_ES_DEPRECATIONS_PAGE_LOAD = 'es_deprecations_page_load'; +export const UIM_KIBANA_DEPRECATIONS_PAGE_LOAD = 'kibana_deprecations_page_load'; +export const UIM_OVERVIEW_PAGE_LOAD = 'overview_page_load'; +export const UIM_REINDEX_OPEN_FLYOUT_CLICK = 'reindex_open_flyout_click'; +export const UIM_REINDEX_CLOSE_FLYOUT_CLICK = 'reindex_close_flyout_click'; +export const UIM_REINDEX_START_CLICK = 'reindex_start_click'; +export const UIM_REINDEX_STOP_CLICK = 'reindex_stop_click'; +export const UIM_BACKUP_DATA_CLOUD_CLICK = 'backup_data_cloud_click'; +export const UIM_BACKUP_DATA_ON_PREM_CLICK = 'backup_data_on_prem_click'; +export const UIM_RESET_LOGS_COUNTER_CLICK = 'reset_logs_counter_click'; +export const UIM_OBSERVABILITY_CLICK = 'observability_click'; +export const UIM_DISCOVER_CLICK = 'discover_click'; +export const UIM_ML_SNAPSHOT_UPGRADE_CLICK = 'ml_snapshot_upgrade_click'; +export const UIM_ML_SNAPSHOT_DELETE_CLICK = 'ml_snapshot_delete_click'; +export const UIM_INDEX_SETTINGS_DELETE_CLICK = 'index_settings_delete_click'; +export const UIM_KIBANA_QUICK_RESOLVE_CLICK = 'kibana_quick_resolve_click'; + +export class UiMetricService { + private usageCollection: UsageCollectionSetup | undefined; + + public setup(usageCollection: UsageCollectionSetup) { + this.usageCollection = usageCollection; + } + + private track(metricType: UiCounterMetricType, eventName: string | string[]) { + if (!this.usageCollection) { + // Usage collection might be disabled in Kibana config. + return; + } + return this.usageCollection.reportUiCounter(UIM_APP_NAME, metricType, eventName); + } + + public trackUiMetric(metricType: UiCounterMetricType, eventName: string | string[]) { + return this.track(metricType, eventName); + } +} + +export const uiMetricService = new UiMetricService(); diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts index bafcae79acc13..2b0ad7241b3af 100644 --- a/x-pack/plugins/upgrade_assistant/public/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -11,6 +11,7 @@ import { Plugin, CoreSetup, PluginInitializerContext } from 'src/core/public'; import { apiService } from './application/lib/api'; import { breadcrumbService } from './application/lib/breadcrumbs'; +import { uiMetricService } from './application/lib/ui_metric'; import { SetupDependencies, StartDependencies, AppDependencies, ClientConfigType } from './types'; export class UpgradeAssistantUIPlugin @@ -18,7 +19,10 @@ export class UpgradeAssistantUIPlugin { constructor(private ctx: PluginInitializerContext) {} - setup(coreSetup: CoreSetup, { management, cloud, share }: SetupDependencies) { + setup( + coreSetup: CoreSetup, + { management, cloud, share, usageCollection }: SetupDependencies + ) { const { readonly, ui: { enabled: isUpgradeAssistantUiEnabled }, @@ -34,45 +38,49 @@ export class UpgradeAssistantUIPlugin nextMajor: kibanaVersion.major + 1, }; - const pluginName = i18n.translate('xpack.upgradeAssistant.appTitle', { - defaultMessage: 'Upgrade Assistant', - }); + const pluginName = i18n.translate('xpack.upgradeAssistant.appTitle', { + defaultMessage: 'Upgrade Assistant', + }); + + if (usageCollection) { + uiMetricService.setup(usageCollection); + } - appRegistrar.registerApp({ - id: 'upgrade_assistant', - title: pluginName, - order: 1, - async mount(params) { - const [coreStart, { data, ...plugins }] = await coreSetup.getStartServices(); + appRegistrar.registerApp({ + id: 'upgrade_assistant', + title: pluginName, + order: 1, + async mount(params) { + const [coreStart, { data, ...plugins }] = await coreSetup.getStartServices(); - const { - chrome: { docTitle }, - } = coreStart; + const { + chrome: { docTitle }, + } = coreStart; - docTitle.change(pluginName); + docTitle.change(pluginName); - const appDependencies: AppDependencies = { - kibanaVersionInfo, - isReadOnlyMode: readonly, - plugins: { - cloud, - share, - // Infra plugin doesnt export anything as a public interface. So the only - // way we have at this stage for checking if the plugin is available or not - // is by checking if the startServices has the `infra` key. - infra: plugins.hasOwnProperty('infra') ? {} : undefined, - }, - services: { - core: coreStart, - data, - history: params.history, - api: apiService, - breadcrumbs: breadcrumbService, - }, - }; + const appDependencies: AppDependencies = { + kibanaVersionInfo, + isReadOnlyMode: readonly, + plugins: { + cloud, + share, + // Infra plugin doesnt export anything as a public interface. So the only + // way we have at this stage for checking if the plugin is available or not + // is by checking if the startServices has the `infra` key. + infra: plugins.hasOwnProperty('infra') ? {} : undefined, + }, + services: { + core: coreStart, + data, + history: params.history, + api: apiService, + breadcrumbs: breadcrumbService, + }, + }; - const { mountManagementSection } = await import('./application/mount_management_section'); - const unmountAppCallback = mountManagementSection(params, appDependencies); + const { mountManagementSection } = await import('./application/mount_management_section'); + const unmountAppCallback = mountManagementSection(params, appDependencies); return () => { docTitle.reset(); diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts index a0e6c5f7d1dff..ace009d9c74aa 100644 --- a/x-pack/plugins/upgrade_assistant/public/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/types.ts @@ -10,7 +10,7 @@ import { ManagementSetup } from 'src/plugins/management/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { SharePluginSetup } from 'src/plugins/share/public'; import { CoreStart } from 'src/core/public'; - +import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; import { CloudSetup } from '../../cloud/public'; import { LicensingPluginStart } from '../../licensing/public'; import { BreadcrumbService } from './application/lib/breadcrumbs'; @@ -26,6 +26,7 @@ export interface SetupDependencies { management: ManagementSetup; share: SharePluginSetup; cloud?: CloudSetup; + usageCollection?: UsageCollectionSetup; } export interface StartDependencies { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts deleted file mode 100644 index caff78390b9d1..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; - -import { upsertUIOpenOption } from './es_ui_open_apis'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry SavedObject UIOpen', () => { - describe('Upsert UIOpen Option', () => { - it('call saved objects internal repository with the correct info', async () => { - const internalRepo = savedObjectsRepositoryMock.create(); - - await upsertUIOpenOption({ - overview: true, - elasticsearch: true, - kibana: true, - savedObjects: { createInternalRepository: () => internalRepo } as any, - }); - - expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(3); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - ['ui_open.overview'] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - ['ui_open.elasticsearch'] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - ['ui_open.kibana'] - ); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts deleted file mode 100644 index 3d463fe4b03ed..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SavedObjectsServiceStart } from 'src/core/server'; -import { - UIOpen, - UIOpenOption, - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, -} from '../../../common/types'; - -interface IncrementUIOpenDependencies { - uiOpenOptionCounter: UIOpenOption; - savedObjects: SavedObjectsServiceStart; -} - -async function incrementUIOpenOptionCounter({ - savedObjects, - uiOpenOptionCounter, -}: IncrementUIOpenDependencies) { - const internalRepository = savedObjects.createInternalRepository(); - - await internalRepository.incrementCounter(UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, [ - `ui_open.${uiOpenOptionCounter}`, - ]); -} - -type UpsertUIOpenOptionDependencies = UIOpen & { savedObjects: SavedObjectsServiceStart }; - -export async function upsertUIOpenOption({ - overview, - elasticsearch, - savedObjects, - kibana, -}: UpsertUIOpenOptionDependencies): Promise { - if (overview) { - await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'overview' }); - } - - if (elasticsearch) { - await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'elasticsearch' }); - } - - if (kibana) { - await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'kibana' }); - } - - return { - overview, - elasticsearch, - kibana, - }; -} diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts deleted file mode 100644 index 6a05e8a697bb8..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; -import { upsertUIReindexOption } from './es_ui_reindex_apis'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry SavedObject UIReindex', () => { - describe('Upsert UIReindex Option', () => { - it('call saved objects internal repository with the correct info', async () => { - const internalRepo = savedObjectsRepositoryMock.create(); - await upsertUIReindexOption({ - close: true, - open: true, - start: true, - stop: true, - savedObjects: { createInternalRepository: () => internalRepo } as any, - }); - - expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(4); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.close`] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.open`] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.start`] - ); - expect(internalRepo.incrementCounter).toHaveBeenCalledWith( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - [`ui_reindex.stop`] - ); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts deleted file mode 100644 index caee1a58a4006..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SavedObjectsServiceStart } from 'src/core/server'; -import { - UIReindex, - UIReindexOption, - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, -} from '../../../common/types'; - -interface IncrementUIReindexOptionDependencies { - uiReindexOptionCounter: UIReindexOption; - savedObjects: SavedObjectsServiceStart; -} - -async function incrementUIReindexOptionCounter({ - savedObjects, - uiReindexOptionCounter, -}: IncrementUIReindexOptionDependencies) { - const internalRepository = savedObjects.createInternalRepository(); - - await internalRepository.incrementCounter(UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, [ - `ui_reindex.${uiReindexOptionCounter}`, - ]); -} - -type UpsertUIReindexOptionDepencies = UIReindex & { savedObjects: SavedObjectsServiceStart }; - -export async function upsertUIReindexOption({ - start, - close, - open, - stop, - savedObjects, -}: UpsertUIReindexOptionDepencies): Promise { - if (close) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'close' }); - } - - if (open) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'open' }); - } - - if (start) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'start' }); - } - - if (stop) { - await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'stop' }); - } - - return { - close, - open, - start, - stop, - }; -} diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts index 50c5b358aa5cb..34d329557f11e 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts @@ -47,26 +47,6 @@ describe('Upgrade Assistant Usage Collector', () => { }; dependencies = { usageCollection, - savedObjects: { - createInternalRepository: jest.fn().mockImplementation(() => { - return { - get: () => { - return { - attributes: { - 'ui_open.overview': 10, - 'ui_open.elasticsearch': 20, - 'ui_open.kibana': 15, - 'ui_reindex.close': 1, - 'ui_reindex.open': 4, - 'ui_reindex.start': 2, - 'ui_reindex.stop': 1, - 'ui_reindex.not_defined': 1, - }, - }; - }, - }; - }), - }, elasticsearch: { client: clusterClient, }, @@ -91,17 +71,6 @@ describe('Upgrade Assistant Usage Collector', () => { callClusterStub ); expect(upgradeAssistantStats).toEqual({ - ui_open: { - overview: 10, - elasticsearch: 20, - kibana: 15, - }, - ui_reindex: { - close: 1, - open: 4, - start: 2, - stop: 1, - }, features: { deprecation_logging: { enabled: true, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index 56932f5e54b06..c535cd14f104d 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -5,43 +5,14 @@ * 2.0. */ -import { get } from 'lodash'; -import { - ElasticsearchClient, - ElasticsearchServiceStart, - ISavedObjectsRepository, - SavedObjectsServiceStart, -} from 'src/core/server'; +import { ElasticsearchClient, ElasticsearchServiceStart } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, - UpgradeAssistantTelemetry, - UpgradeAssistantTelemetrySavedObject, - UpgradeAssistantTelemetrySavedObjectAttributes, -} from '../../../common/types'; +import { UpgradeAssistantTelemetry } from '../../../common/types'; import { isDeprecationLogIndexingEnabled, isDeprecationLoggingEnabled, } from '../es_deprecation_logging_apis'; -async function getSavedObjectAttributesFromRepo( - savedObjectsRepository: ISavedObjectsRepository, - docType: string, - docID: string -) { - try { - return ( - await savedObjectsRepository.get( - docType, - docID - ) - ).attributes; - } catch (e) { - return null; - } -} - async function getDeprecationLoggingStatusValue(esClient: ElasticsearchClient): Promise { try { const { body: loggerDeprecationCallResult } = await esClient.cluster.getSettings({ @@ -57,58 +28,14 @@ async function getDeprecationLoggingStatusValue(esClient: ElasticsearchClient): } } -export async function fetchUpgradeAssistantMetrics( - { client: esClient }: ElasticsearchServiceStart, - savedObjects: SavedObjectsServiceStart -): Promise { - const savedObjectsRepository = savedObjects.createInternalRepository(); - const upgradeAssistantSOAttributes = await getSavedObjectAttributesFromRepo( - savedObjectsRepository, - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID - ); +export async function fetchUpgradeAssistantMetrics({ + client: esClient, +}: ElasticsearchServiceStart): Promise { const deprecationLoggingStatusValue = await getDeprecationLoggingStatusValue( esClient.asInternalUser ); - const getTelemetrySavedObject = ( - upgradeAssistantTelemetrySavedObjectAttrs: UpgradeAssistantTelemetrySavedObjectAttributes | null - ): UpgradeAssistantTelemetrySavedObject => { - const defaultTelemetrySavedObject = { - ui_open: { - overview: 0, - elasticsearch: 0, - kibana: 0, - }, - ui_reindex: { - close: 0, - open: 0, - start: 0, - stop: 0, - }, - }; - - if (!upgradeAssistantTelemetrySavedObjectAttrs) { - return defaultTelemetrySavedObject; - } - - return { - ui_open: { - overview: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.overview', 0), - elasticsearch: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.elasticsearch', 0), - kibana: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.kibana', 0), - }, - ui_reindex: { - close: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.close', 0), - open: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.open', 0), - start: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.start', 0), - stop: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.stop', 0), - }, - } as UpgradeAssistantTelemetrySavedObject; - }; - return { - ...getTelemetrySavedObject(upgradeAssistantSOAttributes), features: { deprecation_logging: { enabled: deprecationLoggingStatusValue, @@ -119,14 +46,12 @@ export async function fetchUpgradeAssistantMetrics( interface Dependencies { elasticsearch: ElasticsearchServiceStart; - savedObjects: SavedObjectsServiceStart; usageCollection: UsageCollectionSetup; } export function registerUpgradeAssistantUsageCollector({ elasticsearch, usageCollection, - savedObjects, }: Dependencies) { const upgradeAssistantUsageCollector = usageCollection.makeUsageCollector({ @@ -143,34 +68,8 @@ export function registerUpgradeAssistantUsageCollector({ }, }, }, - ui_open: { - elasticsearch: { - type: 'long', - _meta: { - description: 'Number of times a user viewed the list of Elasticsearch deprecations.', - }, - }, - overview: { - type: 'long', - _meta: { - description: 'Number of times a user viewed the Overview page.', - }, - }, - kibana: { - type: 'long', - _meta: { - description: 'Number of times a user viewed the list of Kibana deprecations', - }, - }, - }, - ui_reindex: { - close: { type: 'long' }, - open: { type: 'long' }, - start: { type: 'long' }, - stop: { type: 'long' }, - }, }, - fetch: async () => fetchUpgradeAssistantMetrics(elasticsearch, savedObjects), + fetch: async () => fetchUpgradeAssistantMetrics(elasticsearch), }); usageCollection.registerCollector(upgradeAssistantUsageCollector); diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index 2062cf982d15f..717f03758f825 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -142,11 +142,10 @@ export class UpgradeAssistantServerPlugin implements Plugin { registerRoutes(dependencies, this.getWorker.bind(this)); if (usageCollection) { - getStartServices().then(([{ savedObjects: savedObjectsService, elasticsearch }]) => { + getStartServices().then(([{ elasticsearch }]) => { registerUpgradeAssistantUsageCollector({ elasticsearch, usageCollection, - savedObjects: savedObjectsService, }); }); } diff --git a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts index e6a92af53b143..b6c8850376684 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/register_routes.ts @@ -14,7 +14,6 @@ import { registerSystemIndicesMigrationRoutes } from './system_indices_migration import { registerESDeprecationRoutes } from './es_deprecations'; import { registerDeprecationLoggingRoutes } from './deprecation_logging'; import { registerReindexIndicesRoutes, registerBatchReindexIndicesRoutes } from './reindex_indices'; -import { registerTelemetryRoutes } from './telemetry'; import { registerUpdateSettingsRoute } from './update_index_settings'; import { registerMlSnapshotRoutes } from './ml_snapshots'; import { ReindexWorker } from '../lib/reindexing'; @@ -29,7 +28,6 @@ export function registerRoutes(dependencies: RouteDependencies, getWorker: () => registerDeprecationLoggingRoutes(dependencies); registerReindexIndicesRoutes(dependencies, getWorker); registerBatchReindexIndicesRoutes(dependencies, getWorker); - registerTelemetryRoutes(dependencies); registerUpdateSettingsRoute(dependencies); registerMlSnapshotRoutes(dependencies); // Route for cloud to retrieve the upgrade status for ES and Kibana diff --git a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts deleted file mode 100644 index 578cceb702751..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { kibanaResponseFactory } from 'src/core/server'; -import { savedObjectsServiceMock } from 'src/core/server/mocks'; -import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; -import { createRequestMock } from './__mocks__/request.mock'; - -jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ - upsertUIOpenOption: jest.fn(), -})); - -jest.mock('../lib/telemetry/es_ui_reindex_apis', () => ({ - upsertUIReindexOption: jest.fn(), -})); - -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; -import { registerTelemetryRoutes } from './telemetry'; - -/** - * Since these route callbacks are so thin, these serve simply as integration tests - * to ensure they're wired up to the lib functions correctly. Business logic is tested - * more thoroughly in the lib/telemetry tests. - */ -describe('Upgrade Assistant Telemetry API', () => { - let routeDependencies: any; - let mockRouter: MockRouter; - beforeEach(() => { - mockRouter = createMockRouter(); - routeDependencies = { - getSavedObjectsService: () => savedObjectsServiceMock.create(), - router: mockRouter, - }; - registerTelemetryRoutes(routeDependencies); - }); - afterEach(() => jest.clearAllMocks()); - - describe('PUT /api/upgrade_assistant/stats/ui_open', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - overview: true, - elasticsearch: false, - kibana: false, - }; - - (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_open', - })( - routeHandlerContextMock, - createRequestMock({ body: returnPayload }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - overview: true, - elasticsearch: true, - kibana: true, - }; - - (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_open', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - overview: true, - elasticsearch: true, - kibana: true, - }, - }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - (upsertUIOpenOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); - - await expect( - routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_open', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - overview: false, - }, - }), - kibanaResponseFactory - ) - ).rejects.toThrowError('scary error!'); - }); - }); - - describe('PUT /api/upgrade_assistant/stats/ui_reindex', () => { - it('returns correct payload with single option', async () => { - const returnPayload = { - close: false, - open: false, - start: true, - stop: false, - }; - - (upsertUIReindexOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_reindex', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - overview: false, - }, - }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns correct payload with multiple option', async () => { - const returnPayload = { - close: true, - open: true, - start: true, - stop: true, - }; - - (upsertUIReindexOption as jest.Mock).mockResolvedValue(returnPayload); - - const resp = await routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_reindex', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - close: true, - open: true, - start: true, - stop: true, - }, - }), - kibanaResponseFactory - ); - - expect(resp.payload).toEqual(returnPayload); - }); - - it('returns an error if it throws', async () => { - (upsertUIReindexOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); - - await expect( - routeDependencies.router.getHandler({ - method: 'put', - pathPattern: '/api/upgrade_assistant/stats/ui_reindex', - })( - routeHandlerContextMock, - createRequestMock({ - body: { - start: false, - }, - }), - kibanaResponseFactory - ) - ).rejects.toThrowError('scary error!'); - }); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts deleted file mode 100644 index d083b38c7c240..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts +++ /dev/null @@ -1,64 +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 { schema } from '@kbn/config-schema'; -import { API_BASE_PATH } from '../../common/constants'; -import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; -import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; -import { RouteDependencies } from '../types'; - -export function registerTelemetryRoutes({ router, getSavedObjectsService }: RouteDependencies) { - router.put( - { - path: `${API_BASE_PATH}/stats/ui_open`, - validate: { - body: schema.object({ - overview: schema.boolean({ defaultValue: false }), - elasticsearch: schema.boolean({ defaultValue: false }), - kibana: schema.boolean({ defaultValue: false }), - }), - }, - }, - async (ctx, request, response) => { - const { elasticsearch, overview, kibana } = request.body; - return response.ok({ - body: await upsertUIOpenOption({ - savedObjects: getSavedObjectsService(), - elasticsearch, - overview, - kibana, - }), - }); - } - ); - - router.put( - { - path: `${API_BASE_PATH}/stats/ui_reindex`, - validate: { - body: schema.object({ - close: schema.boolean({ defaultValue: false }), - open: schema.boolean({ defaultValue: false }), - start: schema.boolean({ defaultValue: false }), - stop: schema.boolean({ defaultValue: false }), - }), - }, - }, - async (ctx, request, response) => { - const { close, open, start, stop } = request.body; - return response.ok({ - body: await upsertUIReindexOption({ - savedObjects: getSavedObjectsService(), - close, - open, - start, - stop, - }), - }); - } - ); -} diff --git a/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/index.ts b/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/index.ts new file mode 100644 index 0000000000000..5e6e379bd9b2b --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { telemetrySavedObjectMigrations } from './telemetry_saved_object_migrations'; diff --git a/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.test.ts b/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.test.ts new file mode 100644 index 0000000000000..e1250ee0ebfe0 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.test.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { telemetrySavedObjectMigrations } from './telemetry_saved_object_migrations'; + +describe('Telemetry saved object migration', () => { + describe('7.16.0', () => { + test('removes ui_open and ui_reindex attributes while preserving other attributes', () => { + const doc = { + type: 'upgrade-assistant-telemetry', + id: 'upgrade-assistant-telemetry', + attributes: { + 'test.property': 5, + 'ui_open.cluster': 1, + 'ui_open.indices': 1, + 'ui_open.overview': 1, + 'ui_reindex.close': 1, + 'ui_reindex.open': 1, + 'ui_reindex.start': 1, + 'ui_reindex.stop': 1, + }, + references: [], + updated_at: '2021-09-29T21:17:17.410Z', + migrationVersion: {}, + }; + + expect(telemetrySavedObjectMigrations['7.16.0'](doc)).toStrictEqual({ + type: 'upgrade-assistant-telemetry', + id: 'upgrade-assistant-telemetry', + attributes: { 'test.property': 5 }, + references: [], + updated_at: '2021-09-29T21:17:17.410Z', + migrationVersion: {}, + }); + }); + }); +}); diff --git a/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.ts b/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.ts new file mode 100644 index 0000000000000..88540d67b13df --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/saved_object_types/migrations/telemetry_saved_object_migrations.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { get, omit, flow, some } from 'lodash'; +import type { SavedObjectMigrationFn } from 'kibana/server'; + +const v716RemoveUnusedTelemetry: SavedObjectMigrationFn = (doc) => { + // Dynamically defined in 6.7 (https://github.com/elastic/kibana/pull/28878) + // and then statically defined in 7.8 (https://github.com/elastic/kibana/pull/64332). + const attributesBlocklist = [ + 'ui_open.cluster', + 'ui_open.indices', + 'ui_open.overview', + 'ui_reindex.close', + 'ui_reindex.open', + 'ui_reindex.start', + 'ui_reindex.stop', + ]; + + const isDocEligible = some(attributesBlocklist, (attribute: string) => { + return get(doc, 'attributes', attribute); + }); + + if (isDocEligible) { + return { + ...doc, + attributes: omit(doc.attributes, attributesBlocklist), + }; + } + + return doc; +}; + +export const telemetrySavedObjectMigrations = { + '7.16.0': flow(v716RemoveUnusedTelemetry), +}; diff --git a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts index 42d5d339dd050..43cf6c30fccab 100644 --- a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts +++ b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts @@ -7,50 +7,15 @@ import { SavedObjectsType } from 'src/core/server'; -import { UPGRADE_ASSISTANT_TYPE } from '../../common/types'; +import { UPGRADE_ASSISTANT_TELEMETRY } from '../../common/constants'; +import { telemetrySavedObjectMigrations } from './migrations'; export const telemetrySavedObjectType: SavedObjectsType = { - name: UPGRADE_ASSISTANT_TYPE, + name: UPGRADE_ASSISTANT_TELEMETRY, hidden: false, namespaceType: 'agnostic', mappings: { properties: { - ui_open: { - properties: { - overview: { - type: 'long', - null_value: 0, - }, - elasticsearch: { - type: 'long', - null_value: 0, - }, - kibana: { - type: 'long', - null_value: 0, - }, - }, - }, - ui_reindex: { - properties: { - close: { - type: 'long', - null_value: 0, - }, - open: { - type: 'long', - null_value: 0, - }, - start: { - type: 'long', - null_value: 0, - }, - stop: { - type: 'long', - null_value: 0, - }, - }, - }, features: { properties: { deprecation_logging: { @@ -65,4 +30,5 @@ export const telemetrySavedObjectType: SavedObjectsType = { }, }, }, + migrations: telemetrySavedObjectMigrations, }; From 3e4cc95cb31a60d85d80bdb329cb1d5d1388f8bf Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 19 Oct 2021 17:59:07 +0100 Subject: [PATCH 75/93] [Upgrade Assistant] Rename upgrade_status to migration_status (#114755) --- .../migrate_system_indices.test.tsx | 10 +++++----- .../overview/migrate_system_indices/mocks.ts | 10 +++++----- .../migrate_system_indices/step_completion.test.ts | 8 ++++---- x-pack/plugins/upgrade_assistant/common/types.ts | 6 +++--- .../overview/migrate_system_indices/flyout.tsx | 10 +++++----- .../migrate_system_indices/migrate_system_indices.tsx | 8 ++++---- .../use_migrate_system_indices.ts | 2 +- .../server/lib/es_deprecations_status.test.ts | 4 ++-- .../server/lib/es_system_indices_migration.test.ts | 6 +++--- .../server/routes/system_indices_migration.test.ts | 4 ++-- 10 files changed, 34 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx index c5f680319d0ab..f6c69c818b378 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx @@ -45,7 +45,7 @@ describe('Overview - Migrate system indices', () => { component.update(); httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'NO_UPGRADE_NEEDED', + migration_status: 'NO_MIGRATION_NEEDED', }); await actions.clickRetrySystemIndicesButton(); @@ -56,7 +56,7 @@ describe('Overview - Migrate system indices', () => { test('No migration needed', async () => { httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'NO_UPGRADE_NEEDED', + migration_status: 'NO_MIGRATION_NEEDED', }); testBed = await setupOverviewPage(); @@ -72,7 +72,7 @@ describe('Overview - Migrate system indices', () => { test('Migration in progress', async () => { httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'IN_PROGRESS', + migration_status: 'IN_PROGRESS', }); testBed = await setupOverviewPage(); @@ -91,7 +91,7 @@ describe('Overview - Migrate system indices', () => { describe('Migration needed', () => { test('Initial state', async () => { httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', }); testBed = await setupOverviewPage(); @@ -109,7 +109,7 @@ describe('Overview - Migrate system indices', () => { test('Handles errors when migrating', async () => { httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', }); httpRequestsMockHelpers.setSystemIndicesMigrationResponse(undefined, { statusCode: 400, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts index 298f537819507..a810799c434e0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/mocks.ts @@ -8,12 +8,12 @@ import { SystemIndicesMigrationStatus } from '../../../../common/types'; export const systemIndicesMigrationStatus: SystemIndicesMigrationStatus = { - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', features: [ { feature_name: 'security', minimum_index_version: '7.1.1', - upgrade_status: 'ERROR', + migration_status: 'ERROR', indices: [ { index: '.security-7', @@ -24,7 +24,7 @@ export const systemIndicesMigrationStatus: SystemIndicesMigrationStatus = { { feature_name: 'machine_learning', minimum_index_version: '7.1.2', - upgrade_status: 'IN_PROGRESS', + migration_status: 'IN_PROGRESS', indices: [ { index: '.ml-config', @@ -35,7 +35,7 @@ export const systemIndicesMigrationStatus: SystemIndicesMigrationStatus = { { feature_name: 'kibana', minimum_index_version: '7.1.3', - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', indices: [ { index: '.kibana', @@ -46,7 +46,7 @@ export const systemIndicesMigrationStatus: SystemIndicesMigrationStatus = { { feature_name: 'logstash', minimum_index_version: '7.1.4', - upgrade_status: 'NO_UPGRADE_NEEDED', + migration_status: 'NO_MIGRATION_NEEDED', indices: [ { index: '.logstash-config', diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts index c5173481d8dac..9eb0831c3c7a0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/step_completion.test.ts @@ -21,7 +21,7 @@ describe('Overview - Migrate system indices - Step completion', () => { test(`It's complete when no upgrade is needed`, async () => { httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'NO_UPGRADE_NEEDED', + migration_status: 'NO_MIGRATION_NEEDED', }); await act(async () => { @@ -37,7 +37,7 @@ describe('Overview - Migrate system indices - Step completion', () => { test(`It's incomplete when migration is needed`, async () => { httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', }); await act(async () => { @@ -57,7 +57,7 @@ describe('Overview - Migrate system indices - Step completion', () => { // First request should make the step be incomplete httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'IN_PROGRESS', + migration_status: 'IN_PROGRESS', }); testBed = await setupOverviewPage(); @@ -73,7 +73,7 @@ describe('Overview - Migrate system indices - Step completion', () => { expect(exists('migrateSystemIndicesStep-incomplete')).toBe(true); httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ - upgrade_status: 'NO_UPGRADE_NEEDED', + migration_status: 'NO_MIGRATION_NEEDED', }); // Resolve the polling timeout. diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index ac4cd62aa2bea..0de19630bcebd 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -230,12 +230,12 @@ export interface DeprecationLoggingStatus { isDeprecationLoggingEnabled: boolean; } -export type UPGRADE_STATUS = 'UPGRADE_NEEDED' | 'NO_UPGRADE_NEEDED' | 'IN_PROGRESS' | 'ERROR'; +export type MIGRATION_STATUS = 'MIGRATION_NEEDED' | 'NO_MIGRATION_NEEDED' | 'IN_PROGRESS' | 'ERROR'; export interface SystemIndicesMigrationFeature { id?: string; feature_name: string; minimum_index_version: string; - upgrade_status: UPGRADE_STATUS; + migration_status: MIGRATION_STATUS; indices: Array<{ index: string; version: string; @@ -243,7 +243,7 @@ export interface SystemIndicesMigrationFeature { } export interface SystemIndicesMigrationStatus { features: SystemIndicesMigrationFeature[]; - upgrade_status: UPGRADE_STATUS; + migration_status: MIGRATION_STATUS; } export interface SystemIndicesMigrationStarted { features: SystemIndicesMigrationFeature[]; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx index 612fcdc2e4c03..0eac26fae2be3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx @@ -27,7 +27,7 @@ import { import { SystemIndicesMigrationStatus, SystemIndicesMigrationFeature, - UPGRADE_STATUS, + MIGRATION_STATUS, } from '../../../../../common/types'; export interface SystemIndicesFlyoutProps { @@ -84,8 +84,8 @@ const i18nTexts = { ), }; -const renderMigrationStatus = (status: UPGRADE_STATUS) => { - if (status === 'NO_UPGRADE_NEEDED') { +const renderMigrationStatus = (status: MIGRATION_STATUS) => { + if (status === 'NO_MIGRATION_NEEDED') { return ( @@ -100,7 +100,7 @@ const renderMigrationStatus = (status: UPGRADE_STATUS) => { ); } - if (status === 'UPGRADE_NEEDED') { + if (status === 'MIGRATION_NEEDED') { return (

{i18nTexts.needsMigrationLabel}

@@ -150,7 +150,7 @@ const columns = [ render: (name: string) => startCase(name), }, { - field: 'upgrade_status', + field: 'migration_status', name: i18nTexts.statusTableColumn, sortable: true, render: renderMigrationStatus, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx index 75806f43bb19e..7d0405dbbb874 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx @@ -83,10 +83,10 @@ const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) = useMigrateSystemIndices(); useEffect(() => { - setIsComplete(migrationStatus.data?.upgrade_status === 'NO_UPGRADE_NEEDED'); + setIsComplete(migrationStatus.data?.migration_status === 'NO_MIGRATION_NEEDED'); // Depending upon setIsComplete would create an infinite loop. // eslint-disable-next-line react-hooks/exhaustive-deps - }, [migrationStatus.data?.upgrade_status]); + }, [migrationStatus.data?.migration_status]); if (migrationStatus.error) { return ( @@ -111,7 +111,7 @@ const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) = ); } - if (migrationStatus.data?.upgrade_status === 'NO_UPGRADE_NEEDED') { + if (migrationStatus.data?.migration_status === 'NO_MIGRATION_NEEDED') { return ( @@ -127,7 +127,7 @@ const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) = } const isButtonDisabled = migrationStatus.isInitialRequest && migrationStatus.isLoading; - const isMigrating = migrationStatus.data?.upgrade_status === 'IN_PROGRESS'; + const isMigrating = migrationStatus.data?.migration_status === 'IN_PROGRESS'; return ( <> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts index 0d4ea9bfaf35c..d66b4009cd02f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts @@ -37,7 +37,7 @@ export const useMigrateSystemIndices = () => { const { data, error, isLoading, resendRequest, isInitialRequest } = api.useLoadSystemIndicesMigrationStatus(); - const isInProgress = data?.upgrade_status === 'IN_PROGRESS'; + const isInProgress = data?.migration_status === 'IN_PROGRESS'; // We only want to poll for the status while the migration process is in progress. useInterval(resendRequest, isInProgress ? SYSTEM_INDICES_MIGRATION_POLL_INTERVAL_MS : null); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts index d27a02ae97fdd..06c0352ebcdca 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts @@ -46,7 +46,7 @@ describe('getESUpgradeStatus', () => { { feature_name: 'machine_learning', minimum_index_version: '7.1.1', - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', indices: [ { index: '.ml-config', @@ -55,7 +55,7 @@ describe('getESUpgradeStatus', () => { ], }, ], - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', }) ); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.test.ts index 6f4ca5a341218..560d42712b5da 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_system_indices_migration.test.ts @@ -13,7 +13,7 @@ const esUpgradeSystemIndicesStatusMock: SystemIndicesMigrationStatus = { { feature_name: 'machine_learning', minimum_index_version: '7.1.1', - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', indices: [ { index: '.ml-config', @@ -28,7 +28,7 @@ const esUpgradeSystemIndicesStatusMock: SystemIndicesMigrationStatus = { { feature_name: 'security', minimum_index_version: '7.1.1', - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', indices: [ { index: '.ml-config', @@ -37,7 +37,7 @@ const esUpgradeSystemIndicesStatusMock: SystemIndicesMigrationStatus = { ], }, ], - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', }; describe('convertFeaturesToIndicesArray', () => { diff --git a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts index 2d15bed7e29e3..8e928fb3bc7c9 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts @@ -21,7 +21,7 @@ const mockedResponse = { { feature_name: 'security', minimum_index_version: '7.1.1', - upgrade_status: 'NO_UPGRADE_NEEDED', + migration_status: 'NO_MIGRATION_NEEDED', indices: [ { index: '.security-7', @@ -30,7 +30,7 @@ const mockedResponse = { ], }, ], - upgrade_status: 'UPGRADE_NEEDED', + migration_status: 'MIGRATION_NEEDED', }; /** From 6358ceec6c6825250b13d4598f308996039c029d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 19 Oct 2021 22:20:08 +0200 Subject: [PATCH 76/93] [Upgrade Assistant] Swapped reindexing flyouts order (#115046) * [Upgrade Assistant] Changed reindexing steps order, replaced a warning callout with a text element * [Upgrade Assistant] Fixed reindex flyout test and changed warning callout from danger color to warning color * [Upgrade Assistant] Fixed the correct status to show warnings * [Upgrade Assistant] Fixed i18n strings * [Upgrade Assistant] Moved reindex with warnings logic into a function * [Upgrade Assistant] Updated reindex flyout copy * [Upgrade Assistant] Also added a trailing period to the reindex step 3 * [Upgrade Assistant] Fixed i18n strings and step 3 wording * [Upgrade Assistant] Added docs changes Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...-plugin-core-public.doclinksstart.links.md | 1 + .../public/doc_links/doc_links_service.ts | 2 + src/core/public/public.api.md | 1 + .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../checklist_step.test.tsx.snap | 37 +++--- .../__snapshots__/warning_step.test.tsx.snap | 43 +------ .../reindex/flyout/checklist_step.test.tsx | 18 +++ .../reindex/flyout/checklist_step.tsx | 71 ++++++------ .../reindex/flyout/container.tsx | 85 ++++++++------ .../reindex/flyout/progress.test.tsx | 8 +- .../reindex/flyout/progress.tsx | 105 ++++++++++++------ .../reindex/flyout/warning_step.test.tsx | 9 +- .../reindex/flyout/warnings_step.tsx | 102 ++++++++--------- 14 files changed, 257 insertions(+), 229 deletions(-) diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 3535681e73dde..d251d54cd2a94 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -136,6 +136,7 @@ readonly links: { readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; + readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index a18b7c8a24632..82b5dfa47c8de 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -159,6 +159,7 @@ export class DocLinksService { upgradeAssistant: { overview: `${KIBANA_DOCS}upgrade-assistant.html`, batchReindex: `${KIBANA_DOCS}batch-start-resume-reindex.html`, + remoteReindex: `${ELASTICSEARCH_DOCS}docs-reindex.html#reindex-from-remote`, }, rollupJobs: `${KIBANA_DOCS}data-rollups.html`, elasticsearch: { @@ -647,6 +648,7 @@ export interface DocLinksStart { readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; + readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 8e9687747537e..218e1d814f96e 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -603,6 +603,7 @@ export interface DocLinksStart { readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; + readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7e701fb110827..f53ec605ec93d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25171,8 +25171,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.continueButtonLabel": "再インデックスを続ける", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.insufficientPrivilegeCallout.calloutTitle": "このインデックスを再インデックスするための権限がありません", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.backgroundResumeDetail": "再インデックスはバックグラウンドで継続しますが、Kibana がシャットダウンまたは再起動した場合、このページに戻り再インデックスを再開させる必要があります。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.calloutTitle": "インデックスは再インデックス中にドキュメントを投入、更新、または削除できません", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.cantStopDetail": "ドキュメントの更新を停止できない場合、または新しいクラスターに再インデックスする必要がある場合は、異なるアップグレード方法をお勧めします。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.reindexingLabel": "再インデックス中…", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.resumeLabel": "再開", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.runReindexLabel": "再インデックスを実行", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 95d575a7198b0..5ef5a0957908b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25600,8 +25600,6 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.continueButtonLabel": "继续重新索引", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.insufficientPrivilegeCallout.calloutTitle": "您没有足够的权限来重新索引此索引", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.backgroundResumeDetail": "重新索引将在后台继续,但如果 Kibana 关闭或重新启动,您将需要返回此页,才能恢复重新索引。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.calloutTitle": "在重新索引时,索引无法采集、更新或删除文档", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.readonlyCallout.cantStopDetail": "如果您无法停止文档更新或需要重新索引到新的集群中,请考虑使用不同的升级策略。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.reindexingLabel": "正在重新索引……", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.resumeLabel": "恢复", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.runReindexLabel": "运行重新索引", diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index ff2559ecd8302..f3a1723c9c6ea 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -3,35 +3,34 @@ exports[`ChecklistFlyout renders 1`] = ` - - } - > +

+ Learn more + , + } + } />

-
+
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap index bec337087e534..2f68d35b67505 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/warning_step.test.tsx.snap @@ -2,40 +2,7 @@ exports[`WarningsFlyoutStep renders 1`] = ` - - - } - > -

- -

-
- - -

- -

-
- -
+ @@ -59,13 +26,13 @@ exports[`WarningsFlyoutStep renders 1`] = ` grow={false} > diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx index a4cc5bd89aae9..c68f580494b29 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx @@ -14,6 +14,24 @@ import { LoadingState } from '../../../../types'; import type { ReindexState } from '../use_reindex_state'; import { ChecklistFlyoutStep } from './checklist_step'; +jest.mock('../../../../../app_context', () => { + const { docLinksServiceMock } = jest.requireActual( + '../../../../../../../../../../src/core/public/doc_links/doc_links_service.mock' + ); + + return { + useAppContext: () => { + return { + services: { + core: { + docLinks: docLinksServiceMock.createStartContract(), + }, + }, + }; + }, + }; +}); + describe('ChecklistFlyout', () => { const defaultProps = { indexName: 'myIndex', diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx index 91f687eba767b..e0b9b25d73235 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { Fragment, useCallback } from 'react'; +import React, { Fragment } from 'react'; import { EuiButton, @@ -15,20 +15,18 @@ import { EuiFlexItem, EuiFlyoutBody, EuiFlyoutFooter, + EuiLink, EuiSpacer, + EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { METRIC_TYPE } from '@kbn/analytics'; +import { i18n } from '@kbn/i18n'; import { ReindexStatus } from '../../../../../../../common/types'; -import { - uiMetricService, - UIM_REINDEX_START_CLICK, - UIM_REINDEX_STOP_CLICK, -} from '../../../../../lib/ui_metric'; import { LoadingState } from '../../../../types'; import type { ReindexState } from '../use_reindex_state'; import { ReindexProgress } from './progress'; +import { useAppContext } from '../../../../../app_context'; const buttonLabel = (status?: ReindexStatus) => { switch (status) { @@ -50,21 +48,21 @@ const buttonLabel = (status?: ReindexStatus) => { return ( ); case ReindexStatus.cancelled: return ( ); default: return ( ); } @@ -79,22 +77,18 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ startReindex: () => void; cancelReindex: () => void; }> = ({ closeFlyout, reindexState, startReindex, cancelReindex }) => { + const { + services: { + core: { docLinks }, + }, + } = useAppContext(); + const { loadingState, status, hasRequiredPrivileges } = reindexState; const loading = loadingState === LoadingState.Loading || status === ReindexStatus.inProgress; const isCompleted = status === ReindexStatus.completed; const hasFetchFailed = status === ReindexStatus.fetchFailed; const hasReindexingFailed = status === ReindexStatus.failed; - const onStartReindex = useCallback(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_START_CLICK); - startReindex(); - }, [startReindex]); - - const onStopReindex = useCallback(() => { - uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_STOP_CLICK); - cancelReindex(); - }, [cancelReindex]); - return ( @@ -138,33 +132,34 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ )} - - } - color="warning" - iconType="alert" - > +

+ {i18n.translate( + 'xpack.upgradeAssistant.checkupTab.reindexing.flyout.learnMoreLinkLabel', + { + defaultMessage: 'Learn more', + } + )} + + ), + }} />

-
+ - +
@@ -182,7 +177,7 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ fill color={status === ReindexStatus.paused ? 'warning' : 'primary'} iconType={status === ReindexStatus.paused ? 'play' : undefined} - onClick={onStartReindex} + onClick={startReindex} isLoading={loading} disabled={loading || !hasRequiredPrivileges} data-test-subj="startReindexingButton" diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx index 78647e9a51eb0..82d0f57c22a55 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx @@ -5,9 +5,10 @@ * 2.0. */ -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlyoutHeader, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EnrichedDeprecationInfo, ReindexStatus } from '../../../../../../../common/types'; @@ -15,11 +16,11 @@ import type { ReindexStateContext } from '../context'; import { ChecklistFlyoutStep } from './checklist_step'; import { WarningsFlyoutStep } from './warnings_step'; import { DeprecationBadge } from '../../../../shared'; - -enum ReindexFlyoutStep { - reindexWarnings, - checklist, -} +import { + UIM_REINDEX_START_CLICK, + UIM_REINDEX_STOP_CLICK, + uiMetricService, +} from '../../../../../lib/ui_metric'; export interface ReindexFlyoutProps extends ReindexStateContext { deprecation: EnrichedDeprecationInfo; @@ -36,45 +37,54 @@ export const ReindexFlyout: React.FunctionComponent = ({ const { status, reindexWarnings } = reindexState; const { index } = deprecation; - // If there are any warnings and we haven't started reindexing, show the warnings step first. - const [currentFlyoutStep, setCurrentFlyoutStep] = useState( - reindexWarnings && reindexWarnings.length > 0 && status === undefined - ? ReindexFlyoutStep.reindexWarnings - : ReindexFlyoutStep.checklist - ); + const [showWarningsStep, setShowWarningsStep] = useState(false); - let flyoutContents: React.ReactNode; + const onStartReindex = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_START_CLICK); + startReindex(); + }, [startReindex]); - switch (currentFlyoutStep) { - case ReindexFlyoutStep.reindexWarnings: - flyoutContents = ( - setCurrentFlyoutStep(ReindexFlyoutStep.checklist)} - /> - ); - break; - case ReindexFlyoutStep.checklist: - flyoutContents = ( - - ); - break; - default: - throw new Error(`Invalid flyout step: ${currentFlyoutStep}`); - } + const onStopReindex = useCallback(() => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, UIM_REINDEX_STOP_CLICK); + cancelReindex(); + }, [cancelReindex]); + + const startReindexWithWarnings = () => { + if ( + reindexWarnings && + reindexWarnings.length > 0 && + status !== ReindexStatus.inProgress && + status !== ReindexStatus.completed + ) { + setShowWarningsStep(true); + } else { + onStartReindex(); + } + }; + const flyoutContents = showWarningsStep ? ( + setShowWarningsStep(false)} + continueReindex={() => { + setShowWarningsStep(false); + onStartReindex(); + }} + /> + ) : ( + + ); return ( <> @@ -87,6 +97,7 @@ export const ReindexFlyout: React.FunctionComponent = ({ + {flyoutContents} ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx index 971ea9d550e01..1ee4cf2453bdc 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx @@ -52,15 +52,15 @@ describe('ReindexProgress', () => { Object { "status": "inProgress", "title": , }, Object { "status": "incomplete", "title": , @@ -82,7 +82,7 @@ describe('ReindexProgress', () => { Object { "status": "incomplete", "title": , diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx index f5dc04783b031..cf32a8bb3ab65 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { ReactNode } from 'react'; import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink, EuiText, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -42,11 +42,18 @@ const ReindexingDocumentsStepTitle: React.FunctionComponent<{ <> ); } + + // step is in progress after the new index is created and while it's not completed yet + const stepInProgress = + status === ReindexStatus.inProgress && + (lastCompletedStep === ReindexStep.newIndexCreated || + lastCompletedStep === ReindexStep.reindexStarted); + // but the reindex can only be cancelled after it has started const showCancelLink = status === ReindexStatus.inProgress && lastCompletedStep === ReindexStep.reindexStarted; @@ -89,10 +96,17 @@ const ReindexingDocumentsStepTitle: React.FunctionComponent<{ return ( - + {stepInProgress ? ( + + ) : ( + + )} {showCancelLink && ( @@ -110,6 +124,47 @@ const ReindexingDocumentsStepTitle: React.FunctionComponent<{ }; const orderedSteps = Object.values(ReindexStep).sort() as number[]; +const getStepTitle = (step: ReindexStep, inProgress?: boolean): ReactNode => { + if (step === ReindexStep.readonly) { + return inProgress ? ( + + ) : ( + + ); + } + if (step === ReindexStep.newIndexCreated) { + return inProgress ? ( + + ) : ( + + ); + } + if (step === ReindexStep.aliasCreated) { + return inProgress ? ( + + ) : ( + + ); + } +}; /** * Displays a list of steps in the reindex operation, the current status, a progress bar, @@ -125,33 +180,39 @@ export const ReindexProgress: React.FunctionComponent<{ status, reindexTaskPercComplete, } = props.reindexState; - const stepDetails = (thisStep: ReindexStep): Pick => { + const getProgressStep = (thisStep: ReindexStep): StepProgressStep => { const previousStep = orderedSteps[orderedSteps.indexOf(thisStep) - 1]; if (status === ReindexStatus.failed && lastCompletedStep === previousStep) { return { + title: getStepTitle(thisStep), status: 'failed', children: , }; } else if (status === ReindexStatus.paused && lastCompletedStep === previousStep) { return { + title: getStepTitle(thisStep), status: 'paused', children: , }; } else if (status === ReindexStatus.cancelled && lastCompletedStep === previousStep) { return { + title: getStepTitle(thisStep), status: 'cancelled', }; } else if (status === undefined || lastCompletedStep < previousStep) { return { + title: getStepTitle(thisStep), status: 'incomplete', }; } else if (lastCompletedStep === previousStep) { return { + title: getStepTitle(thisStep, true), status: 'inProgress', }; } else { return { + title: getStepTitle(thisStep), status: 'complete', }; } @@ -194,34 +255,10 @@ export const ReindexProgress: React.FunctionComponent<{ } const steps = [ - { - title: ( - - ), - ...stepDetails(ReindexStep.readonly), - }, - { - title: ( - - ), - ...stepDetails(ReindexStep.newIndexCreated), - }, + getProgressStep(ReindexStep.readonly), + getProgressStep(ReindexStep.newIndexCreated), reindexingDocsStep, - { - title: ( - - ), - ...stepDetails(ReindexStep.aliasCreated), - }, + getProgressStep(ReindexStep.aliasCreated), ]; return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx index 287048d8f257e..11caed5e03a66 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx @@ -43,10 +43,9 @@ jest.mock('../../../../../app_context', () => { describe('WarningsFlyoutStep', () => { const defaultProps = { - advanceNextStep: jest.fn(), warnings: [] as ReindexWarning[], - closeFlyout: jest.fn(), - renderGlobalCallouts: jest.fn(), + hideWarningsStep: jest.fn(), + continueReindex: jest.fn(), }; it('renders', () => { @@ -80,7 +79,7 @@ describe('WarningsFlyoutStep', () => { const button = wrapper.find('EuiButton'); button.simulate('click'); - expect(defaultPropsWithWarnings.advanceNextStep).not.toHaveBeenCalled(); + expect(defaultPropsWithWarnings.continueReindex).not.toHaveBeenCalled(); // first warning (customTypeName) wrapper.find(`input#${idForWarning(0)}`).simulate('change'); @@ -88,7 +87,7 @@ describe('WarningsFlyoutStep', () => { wrapper.find(`input#${idForWarning(1)}`).simulate('change'); button.simulate('click'); - expect(defaultPropsWithWarnings.advanceNextStep).toHaveBeenCalled(); + expect(defaultPropsWithWarnings.continueReindex).toHaveBeenCalled(); }); } }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx index 0596c692a9f38..d8909d4ea039f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx @@ -41,9 +41,9 @@ const warningToComponentMap: { export const idForWarning = (id: number) => `reindexWarning-${id}`; interface WarningsConfirmationFlyoutProps { - closeFlyout: () => void; + hideWarningsStep: () => void; + continueReindex: () => void; warnings: ReindexWarning[]; - advanceNextStep: () => void; } /** @@ -52,8 +52,8 @@ interface WarningsConfirmationFlyoutProps { */ export const WarningsFlyoutStep: React.FunctionComponent = ({ warnings, - closeFlyout, - advanceNextStep, + hideWarningsStep, + continueReindex, }) => { const { services: { @@ -86,64 +86,66 @@ export const WarningsFlyoutStep: React.FunctionComponent - - } - color="danger" - iconType="alert" - > -

- -

-
- - - -

- -

-
- - - {warnings.map((warning, index) => { - const WarningCheckbox = warningToComponentMap[warning.warningType]; - return ( - - ); - })} + {warnings.length > 0 && ( + <> + + } + color="warning" + iconType="alert" + > +

+ +

+
+ + +

+ +

+
+ + {warnings.map((warning, index) => { + const WarningCheckbox = warningToComponentMap[warning.warningType]; + return ( + + ); + })} + + )}
- + - + From 729c99d3e6ec0ce4f255498be338c73b00eb1823 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 20 Oct 2021 00:40:05 +0100 Subject: [PATCH 77/93] [Upgrade Assistant] Hide features that don't need to be migrated from flyout (#115535) * Filter out system indices that dont require migration on server side * Rename to attrs to migration * Update flyout snapshot. --- .../routes/system_indices_migration.test.ts | 18 +++++++++++++++++- .../server/routes/system_indices_migration.ts | 7 ++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts index 8e928fb3bc7c9..910748661ac41 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.test.ts @@ -29,6 +29,17 @@ const mockedResponse = { }, ], }, + { + feature_name: 'kibana', + minimum_index_version: '7.1.2', + upgrade_status: 'MIGRATION_NEEDED', + indices: [ + { + index: '.kibana', + version: '7.1.2', + }, + ], + }, ], migration_status: 'MIGRATION_NEEDED', }; @@ -75,7 +86,12 @@ describe('Migrate system indices API', () => { method: 'GET', path: '/_migration/system_features', }); - expect(resp.payload).toEqual(mockedResponse); + expect(resp.payload).toEqual({ + ...mockedResponse, + features: mockedResponse.features.filter( + (feature) => feature.migration_status !== 'NO_MIGRATION_NEEDED' + ), + }); }); it('returns an error if it throws', async () => { diff --git a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts index dbb0cca7502bb..67f91aa08a076 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/system_indices_migration.ts @@ -34,7 +34,12 @@ export function registerSystemIndicesMigrationRoutes({ const status = await getESSystemIndicesMigrationStatus(client.asCurrentUser); return response.ok({ - body: status, + body: { + ...status, + features: status.features.filter( + (feature) => feature.migration_status !== 'NO_MIGRATION_NEEDED' + ), + }, }); } catch (error) { return handleEsError({ error, response }); From e3343eb0f2aa9fdec27f1929f3a810ca1436feca Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 19 Oct 2021 21:31:33 -0700 Subject: [PATCH 78/93] Refine Upgrade Assistant copy. (#115472) --- ...-plugin-core-public.doclinksstart.links.md | 3 ++ .../public/doc_links/doc_links_service.ts | 7 +++++ src/core/public/public.api.md | 3 ++ .../fix_logs_step/fix_logs_step.test.tsx | 4 +-- .../overview/overview.test.tsx | 7 ++--- .../index_settings/resolution_table_cell.tsx | 2 +- .../ml_snapshots/resolution_table_cell.tsx | 2 +- .../reindex/flyout/warning_step_checkbox.tsx | 2 +- .../reindex/resolution_table_cell.tsx | 2 +- .../es_deprecations/es_deprecations.tsx | 2 +- .../es_deprecations_table_cells.tsx | 2 +- .../deprecation_details_flyout.tsx | 30 +++++++------------ .../kibana_deprecations.tsx | 19 ++---------- .../resolution_table_cell.tsx | 4 +-- .../overview/backup_step/on_prem_backup.tsx | 2 +- .../fix_issues_step/fix_issues_step.tsx | 10 ++----- .../deprecation_logging_toggle.tsx | 4 +-- .../deprecations_count_checkpoint.tsx | 2 +- .../overview/fix_logs_step/fix_logs_step.tsx | 4 +-- .../migrate_system_indices/flyout.tsx | 16 +++++----- .../migrate_system_indices.tsx | 22 ++++---------- .../use_migrate_system_indices.ts | 4 +-- .../components/overview/overview.tsx | 10 ++----- .../overview/upgrade_step/upgrade_step.tsx | 20 ++++++------- 24 files changed, 75 insertions(+), 108 deletions(-) diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index d251d54cd2a94..6229339fd588d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -10,6 +10,9 @@ readonly links: { readonly settings: string; readonly elasticStackGetStarted: string; + readonly upgrade: { + readonly upgradingElasticStack: string; + }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 82b5dfa47c8de..c345fe0c9d729 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -20,6 +20,7 @@ export class DocLinksService { public start({ injectedMetadata }: StartDeps): DocLinksStart { const DOC_LINK_VERSION = injectedMetadata.getKibanaBranch(); const ELASTIC_WEBSITE_URL = 'https://www.elastic.co/'; + const STACK_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack/${DOC_LINK_VERSION}/`; const ELASTICSEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`; const KIBANA_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/`; const FLEET_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/fleet/${DOC_LINK_VERSION}/`; @@ -34,6 +35,9 @@ export class DocLinksService { links: { settings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/settings.html`, elasticStackGetStarted: `${STACK_GETTING_STARTED}get-started-elastic-stack.html`, + upgrade: { + upgradingElasticStack: `${STACK_DOCS}upgrading-elastic-stack.html`, + }, apm: { kibanaSettings: `${KIBANA_DOCS}apm-settings-in-kibana.html`, supportedServiceMaps: `${KIBANA_DOCS}service-maps.html#service-maps-supported`, @@ -522,6 +526,9 @@ export interface DocLinksStart { readonly links: { readonly settings: string; readonly elasticStackGetStarted: string; + readonly upgrade: { + readonly upgradingElasticStack: string; + }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 218e1d814f96e..736371dda94f4 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -477,6 +477,9 @@ export interface DocLinksStart { readonly links: { readonly settings: string; readonly elasticStackGetStarted: string; + readonly upgrade: { + readonly upgradingElasticStack: string; + }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx index 7d4b6b8518dff..8b68f5ee449a8 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx @@ -268,7 +268,7 @@ describe('Overview - Fix deprecation logs step', () => { expect(find('hasWarningsCallout').text()).toContain('10'); }); - test('No deprecation warnings', async () => { + test('No deprecation issues', async () => { httpRequestsMockHelpers.setLoadDeprecationLogsCountResponse({ count: 0, }); @@ -282,7 +282,7 @@ describe('Overview - Fix deprecation logs step', () => { component.update(); expect(exists('noWarningsCallout')).toBe(true); - expect(find('noWarningsCallout').text()).toContain('No deprecation warnings'); + expect(find('noWarningsCallout').text()).toContain('No deprecation issues'); }); test('Handles errors and can retry', async () => { diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.test.tsx index ca46f1c90dbd8..2d318f60149d0 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/overview.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { setupEnvironment, kibanaVersion } from '../helpers'; +import { setupEnvironment } from '../helpers'; import { OverviewTestBed, setupOverviewPage } from './overview.helpers'; describe('Overview Page', () => { @@ -22,12 +22,11 @@ describe('Overview Page', () => { }); describe('Documentation links', () => { - test('Has a whatsNew link and it references nextMajor version', () => { + test('Has a whatsNew link and it references target version', () => { const { exists, find } = testBed; - const nextMajor = kibanaVersion.major + 1; expect(exists('whatsNewLink')).toBe(true); - expect(find('whatsNewLink').text()).toContain(`${nextMajor}.0`); + expect(find('whatsNewLink').text()).toContain('8'); }); test('Has a link for upgrade assistant in page header', () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/resolution_table_cell.tsx index a5a586927c811..f982e84dce6da 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/index_settings/resolution_table_cell.tsx @@ -47,7 +47,7 @@ const i18nTexts = { 'xpack.upgradeAssistant.esDeprecations.indexSettings.resolutionTooltipLabel', { defaultMessage: - 'Resolve this deprecation by removing settings from this index. This is an automated resolution.', + 'Resolve this issue by removing settings from this index. This issue can be resolved automatically.', } ), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/resolution_table_cell.tsx index 7963701b5c543..1c3e23d0b6ca6 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/ml_snapshots/resolution_table_cell.tsx @@ -66,7 +66,7 @@ const i18nTexts = { 'xpack.upgradeAssistant.esDeprecations.mlSnapshots.resolutionTooltipLabel', { defaultMessage: - 'Resolve this deprecation by upgrading or deleting a job model snapshot. This is an automated resolution.', + 'Resolve this issue by upgrading or deleting a job model snapshot. This issue can be resolved automatically.', } ), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx index a5e3260167218..904e9a5e1fec6 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx @@ -105,7 +105,7 @@ export const CustomTypeNameWarningCheckbox: React.FunctionComponent{meta!.typeName as string}, }} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx index d743a7d3018dc..b181e666c17e2 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx @@ -71,7 +71,7 @@ const i18nTexts = { 'xpack.upgradeAssistant.esDeprecations.reindex.resolutionTooltipLabel', { defaultMessage: - 'Resolve this deprecation by reindexing this index. This is an automated resolution.', + 'Resolve this issue by reindexing this index. This issue can be resolved automatically.', } ), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index 7c3394d5a9c0f..270f597cb964f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -46,7 +46,7 @@ const i18nTexts = { }), pageDescription: i18n.translate('xpack.upgradeAssistant.esDeprecations.pageDescription', { defaultMessage: - 'Resolve all critical issues before upgrading. Before making changes, ensure you have a current snapshot of your cluster. Some issues may require reindexing to resolve. ', + 'Resolve all critical issues before upgrading. Before making changes, ensure you have a current snapshot of your cluster. Indices created before 7.0 must be reindexed or removed. To start multiple reindexing tasks in a single request, use the Kibana batch reindexing API.', }), isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { defaultMessage: 'Loading deprecation issues…', diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx index 0a075e049495f..472ecccb4f02f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/es_deprecations_table_cells.tsx @@ -30,7 +30,7 @@ const i18nTexts = { manualCellTooltipLabel: i18n.translate( 'xpack.upgradeAssistant.esDeprecations.reindex.manualCellTooltipLabel', { - defaultMessage: 'Resolve this deprecation manually.', + defaultMessage: 'This issue needs to be resolved manually.', } ), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx index 041e617d2a020..baf725b48e6af 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -68,22 +68,10 @@ const i18nTexts = { defaultMessage: 'Resolution in progress…', } ), - quickResolveCalloutTitle: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveCalloutTitle', - { - defaultMessage: 'Quick resolve action available', - } - ), - quickResolveErrorTitle: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveErrorTitle', - { - defaultMessage: 'Error resolving deprecation', - } - ), - quickResolveCalloutDescription: ( + quickResolveCalloutTitle: ( @@ -95,10 +83,16 @@ const i18nTexts = { }} /> ), + quickResolveErrorTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveErrorTitle', + { + defaultMessage: 'Error resolving issue', + } + ), manualFixTitle: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecations.flyout.manualFixTitle', { - defaultMessage: 'Fix manually', + defaultMessage: 'How to fix', } ), }; @@ -181,9 +175,7 @@ export const DeprecationDetailsFlyout = ({ color="primary" iconType="iInCircle" data-test-subj="quickResolveCallout" - > -

{i18nTexts.quickResolveCalloutDescription}

- + /> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 22a67b227fd8c..3b4cd5acafb95 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -10,7 +10,6 @@ import uuid from 'uuid'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiPageContent, EuiPageHeader, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { METRIC_TYPE } from '@kbn/analytics'; import type { DomainDeprecationDetails } from 'kibana/public'; @@ -30,21 +29,9 @@ const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { defaultMessage: 'Kibana deprecation issues', }), - pageDescription: ( - - {i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.quickResolveText', { - defaultMessage: 'Quick Resolve', - })} - - ), - }} - /> - ), + pageDescription: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageDescription', { + defaultMessage: 'Resolve all critical issues before upgrading.', + }), docLinkText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.docLinkText', { defaultMessage: 'Documentation', }), diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx index aef52fe07a183..daf276b7ed3f8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolution_table_cell.tsx @@ -29,7 +29,7 @@ const i18nTexts = { manualCellTooltipLabel: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecations.table.manualCellTooltipLabel', { - defaultMessage: 'Resolve this deprecation manually.', + defaultMessage: 'This issue needs to be resolved manually.', } ), automatedCellLabel: i18n.translate( @@ -59,7 +59,7 @@ const i18nTexts = { automatedCellTooltipLabel: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecations.table.automatedCellTooltipLabel', { - defaultMessage: 'This is an automated resolution.', + defaultMessage: 'This issue can be resolved automatically.', } ), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx index 69100b36db7eb..e512eb5a301dc 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/backup_step/on_prem_backup.tsx @@ -46,7 +46,7 @@ export const OnPremBackup: React.FunctionComponent = () => {

{i18n.translate('xpack.upgradeAssistant.overview.backupStepDescription', { - defaultMessage: 'Back up your data before addressing any deprecation issues.', + defaultMessage: 'Make sure you have a current snapshot before making any changes.', })}

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx index 590bfac96770d..61d25404b2aee 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_issues_step/fix_issues_step.tsx @@ -25,10 +25,6 @@ interface Props { setIsComplete: OverviewStepProps['setIsComplete']; } -interface StepProps extends OverviewStepProps { - nextMajor: number; -} - const FixIssuesStep: FunctionComponent = ({ setIsComplete }) => { // We consider ES and Kibana issues to be fixed when there are 0 critical issues. const [isEsFixed, setIsEsFixed] = useState(false); @@ -54,10 +50,9 @@ const FixIssuesStep: FunctionComponent = ({ setIsComplete }) => { }; export const getFixIssuesStep = ({ - nextMajor, isComplete, setIsComplete, -}: StepProps): EuiStepProps => { +}: OverviewStepProps): EuiStepProps => { const status = isComplete ? 'complete' : 'incomplete'; return { @@ -70,8 +65,7 @@ export const getFixIssuesStep = ({

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx index 0df75a426901e..cddf5101a4b43 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecation_logging_toggle/deprecation_logging_toggle.tsx @@ -48,10 +48,10 @@ const i18nTexts = { defaultMessage: 'Error', }), buttonLabel: i18n.translate('xpack.upgradeAssistant.overview.deprecationLogs.buttonLabel', { - defaultMessage: 'Enable deprecation logging and indexing', + defaultMessage: 'Enable deprecation log collection', }), loadingLogsLabel: i18n.translate('xpack.upgradeAssistant.overview.loadingLogsLabel', { - defaultMessage: 'Loading log collection state…', + defaultMessage: 'Loading deprecation log collection state…', }), }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx index 7d4941174b93b..6ce1fec32d66c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx @@ -19,7 +19,7 @@ const i18nTexts = { calloutTitle: (warningsCount: number, previousCheck: string) => ( ( @@ -66,7 +66,7 @@ const i18nTexts = { 'xpack.upgradeAssistant.overview.deprecationLogs.deprecationWarningBody', { defaultMessage: - 'Go to your logs directory to view the deprecation logs or enable log collecting to see them in the UI.', + 'Go to your logs directory to view the deprecation logs or enable deprecation log collection to see them in Kibana.', } ), deniedPrivilegeTitle: i18n.translate( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx index 0eac26fae2be3..632994d4948a8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/flyout.tsx @@ -33,7 +33,6 @@ import { export interface SystemIndicesFlyoutProps { closeFlyout: () => void; data: SystemIndicesMigrationStatus; - nextMajor: number; } const i18nTexts = { @@ -46,12 +45,13 @@ const i18nTexts = { flyoutTitle: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.flyoutTitle', { defaultMessage: 'Migrate system indices', }), - flyoutDescription: (nextMajor: number) => - i18n.translate('xpack.upgradeAssistant.overview.systemIndices.flyoutDescription', { + flyoutDescription: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.flyoutDescription', + { defaultMessage: - 'Migrate the indices that store information for the following features before you upgrade to {nextMajor}.0.', - values: { nextMajor }, - }), + 'Migrate the indices that store information for the following features before you upgrade.', + } + ), migrationCompleteLabel: i18n.translate( 'xpack.upgradeAssistant.overview.systemIndices.migrationCompleteLabel', { @@ -157,7 +157,7 @@ const columns = [ }, ]; -export const SystemIndicesFlyout = ({ closeFlyout, data, nextMajor }: SystemIndicesFlyoutProps) => { +export const SystemIndicesFlyout = ({ closeFlyout, data }: SystemIndicesFlyoutProps) => { return ( <> @@ -167,7 +167,7 @@ export const SystemIndicesFlyout = ({ closeFlyout, data, nextMajor }: SystemIndi -

{i18nTexts.flyoutDescription(nextMajor)}

+

{i18nTexts.flyoutDescription}

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx index 7d0405dbbb874..e54568117789a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx @@ -8,7 +8,6 @@ import React, { FunctionComponent, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiText, EuiButton, @@ -28,21 +27,13 @@ interface Props { setIsComplete: OverviewStepProps['setIsComplete']; } -interface StepProps extends OverviewStepProps { - nextMajor: number; -} - const i18nTexts = { title: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.title', { defaultMessage: 'Migrate system indices', }), - bodyDescription: (nextMajor: number) => ( - - ), + bodyDescription: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.body', { + defaultMessage: 'Migrate the indices that store system information before you upgrade.', + }), startButtonLabel: i18n.translate( 'xpack.upgradeAssistant.overview.systemIndices.startButtonLabel', { @@ -64,7 +55,7 @@ const i18nTexts = { viewSystemIndicesStatus: i18n.translate( 'xpack.upgradeAssistant.overview.systemIndices.viewSystemIndicesStatus', { - defaultMessage: 'View migration information', + defaultMessage: 'View migration details', } ), retryButtonLabel: i18n.translate( @@ -172,10 +163,9 @@ const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) = }; export const getMigrateSystemIndicesStep = ({ - nextMajor, isComplete, setIsComplete, -}: StepProps): EuiStepProps => { +}: OverviewStepProps): EuiStepProps => { const status = isComplete ? 'complete' : 'incomplete'; return { @@ -185,7 +175,7 @@ export const getMigrateSystemIndicesStep = ({ children: ( <> -

{i18nTexts.bodyDescription(nextMajor)}

+

{i18nTexts.bodyDescription}

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts index d66b4009cd02f..d38e73562816e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/use_migrate_system_indices.ts @@ -26,7 +26,6 @@ interface MigrationStatus { export const useMigrateSystemIndices = () => { const { services: { api }, - kibanaVersionInfo: { nextMajor }, } = useAppContext(); const [showFlyout, setShowFlyout] = useState(false); @@ -57,7 +56,6 @@ export const useMigrateSystemIndices = () => { Component: SystemIndicesFlyout, props: { data: data!, - nextMajor, closeFlyout, }, flyoutProps: { @@ -65,7 +63,7 @@ export const useMigrateSystemIndices = () => { }, }); } - }, [addContentToGlobalFlyout, data, showFlyout, closeFlyout, nextMajor]); + }, [addContentToGlobalFlyout, data, showFlyout, closeFlyout]); const beginSystemIndicesMigration = useCallback(async () => { const { error: startMigrationError } = await api.migrateSystemIndices(); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index 192c0bbd9e649..1e7961f8ea782 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -33,7 +33,6 @@ type OverviewStep = 'backup' | 'migrate_system_indices' | 'fix_issues' | 'fix_lo export const Overview: FunctionComponent = () => { const { - kibanaVersionInfo: { nextMajor }, services: { breadcrumbs, core: { docLinks }, @@ -73,7 +72,7 @@ export const Overview: FunctionComponent = () => { defaultMessage: 'Upgrade Assistant', })} description={i18n.translate('xpack.upgradeAssistant.overview.pageDescription', { - defaultMessage: 'Get ready for the next version of the Elastic Stack!', + defaultMessage: 'Get ready for the next version of Elastic!', })} rightSideItems={[ { @@ -110,12 +108,10 @@ export const Overview: FunctionComponent = () => { setIsComplete: setCompletedStep.bind(null, 'backup'), }), getMigrateSystemIndicesStep({ - nextMajor, isComplete: isStepComplete('migrate_system_indices'), setIsComplete: setCompletedStep.bind(null, 'migrate_system_indices'), }), getFixIssuesStep({ - nextMajor, isComplete: isStepComplete('fix_issues'), setIsComplete: setCompletedStep.bind(null, 'fix_issues'), }), @@ -123,7 +119,7 @@ export const Overview: FunctionComponent = () => { isComplete: isStepComplete('fix_logs'), setIsComplete: setCompletedStep.bind(null, 'fix_logs'), }), - getUpgradeStep({ nextMajor }), + getUpgradeStep(), ]} /> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx index 4af4a345be89d..b3a3179ed9079 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/upgrade_step/upgrade_step.tsx @@ -20,20 +20,18 @@ import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import { useAppContext } from '../../../app_context'; const i18nTexts = { - upgradeStepTitle: (nextMajor: number) => - i18n.translate('xpack.upgradeAssistant.overview.upgradeStepTitle', { - defaultMessage: 'Install {nextMajor}.0', - values: { nextMajor }, - }), + upgradeStepTitle: i18n.translate('xpack.upgradeAssistant.overview.upgradeStepTitle', { + defaultMessage: 'Upgrade to Elastic 8.x', + }), upgradeStepDescription: i18n.translate('xpack.upgradeAssistant.overview.upgradeStepDescription', { defaultMessage: - "Once you've resolved all critical issues and verified that your applications are ready, you can upgrade the Elastic Stack. Be sure to back up your data again before upgrading.", + 'Once you’ve resolved all critical issues and verified that your applications are ready, you can upgrade to Elastic 8.x. Be sure to back up your data again before upgrading.', }), upgradeStepDescriptionForCloud: i18n.translate( 'xpack.upgradeAssistant.overview.upgradeStepDescriptionForCloud', { defaultMessage: - "Once you've resolved all critical issues and verified that your applications are ready, you can upgrade the Elastic Stack. Upgrade your deployment on Elastic Cloud.", + "Once you've resolved all critical issues and verified that your applications are ready, you can upgrade to Elastic 8.x. Be sure to back up your data again before upgrading. Upgrade your deployment on Elastic Cloud.", } ), upgradeStepLink: i18n.translate('xpack.upgradeAssistant.overview.upgradeStepLink', { @@ -75,7 +73,7 @@ const UpgradeStep = () => { { } else { callToAction = ( { ); }; -export const getUpgradeStep = ({ nextMajor }: { nextMajor: number }): EuiStepProps => { +export const getUpgradeStep = (): EuiStepProps => { return { - title: i18nTexts.upgradeStepTitle(nextMajor), + title: i18nTexts.upgradeStepTitle, status: 'incomplete', 'data-test-subj': 'upgradeStep', children: , From 6b48b2d6d1b544e9a230c8a9aa45a295ce7411e2 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 20 Oct 2021 09:58:07 +0200 Subject: [PATCH 79/93] Remove unused file --- cherry.sh | 176 ------------------------------------------------------ 1 file changed, 176 deletions(-) delete mode 100644 cherry.sh diff --git a/cherry.sh b/cherry.sh deleted file mode 100644 index 155bec683225f..0000000000000 --- a/cherry.sh +++ /dev/null @@ -1,176 +0,0 @@ -#!/bin/bash - -git cherry-pick ec3c28f29590d2d916826fb066fad059f3eb3152 --strategy-option theirs - - -git cherry-pick af6b908df145576f7249efeb08c9b33bd3805a29 --strategy-option theirs - - -git cherry-pick 03e3baad4d95bdb35269261b55006ecb5e978b8c --strategy-option theirs - - -git cherry-pick 4a14a94942e798b8753639fb82d9cb06cbb0d8f4 --strategy-option theirs - - -git cherry-pick 77fe9ecf306f676f1ff39a52c57a8012e12b0f0a --strategy-option theirs - - -git cherry-pick 7947341c823acb01029a5954a4b55e61a4ed3b43 --strategy-option theirs - - -git cherry-pick 7c79a81b25845304d7bfdd74f5fb3dd77b1aef93 --strategy-option theirs - - -git cherry-pick ec09a417c2ce16b452c3c9ec711553b2112d85c9 --strategy-option theirs - - -git cherry-pick 047fe77093b87ff45c2a6a2fbb3fe4284de8bead --strategy-option theirs - - -git cherry-pick 986ac3b3733ca57ce5cd18f5a66cbcef6e0a91d4 --strategy-option theirs - - -git cherry-pick efdc7d579a4aacffed757ba01593c43aac449740 --strategy-option theirs - - -git cherry-pick f558a7932fe7d7cc7e62f139fdc79fcf17550871 --strategy-option theirs - - -git cherry-pick 0f451a577b268c3f65eda235713bec3978400b91 --strategy-option theirs - - -git cherry-pick f15250e7845afc2a12a26f157ecffc08125c3d31 --strategy-option theirs - - -git cherry-pick ee32afb8490746d290b119440fea85869984c4ba --strategy-option theirs - - -git cherry-pick 1a74022b023f0013d27b186d05db186d1939682a --strategy-option theirs - - -git cherry-pick de660291d421ebbf65308d0fde81e1de8fb16e2d --strategy-option theirs - - -git cherry-pick 25de6438383f86f9cffcd87f5359634cb8048029 --strategy-option theirs - - -git cherry-pick d4dbce0e1e2deb59093cab2baf8eef1d3661f8a3 --strategy-option theirs - - -git cherry-pick 48b25a611ca85f823a9236112ffdaea8118c7f2e --strategy-option theirs - - -git cherry-pick 7779b38aea10ad7983379f60004fae5ce51c5232 --strategy-option theirs - - -git cherry-pick 7515700242278753e2526093a89652edb23ec98e --strategy-option theirs - - -git cherry-pick af9d3f5f42c4c26f4e814ab364941fe994500d5a --strategy-option theirs - - -git cherry-pick 67871d5719b96d1f5cb7242e700b226e3dd4ed3b --strategy-option theirs - - -git cherry-pick 5250db866817873dfc9ca862f3a68e24b3f0fa15 --strategy-option theirs - - -git cherry-pick 426bda8432201bcb55ee83629464b71d8b2614fb --strategy-option theirs - - -git cherry-pick 252889814fc144a34a0f34f6fa726a9b6b75a41e --strategy-option theirs - - -git cherry-pick 5393b374d9ee97107e685eec24c942a422d3ff84 --strategy-option theirs - - -git cherry-pick e23c26fcbd5fd501d6c436097ed3035a98322e33 --strategy-option theirs - - -git cherry-pick 8dd4122285edd2c5981432acd8269382117371ab --strategy-option theirs - - -git cherry-pick c6152461155ddfa6714270099267f28ec147ac1b --strategy-option theirs - - -git cherry-pick ac94ed9aaa3ed62136c79dfa59421389b55c2936 --strategy-option theirs - - -git cherry-pick d7ce247f813763e8ee9fd7faf80c754481a8b260 --strategy-option theirs - - -git cherry-pick 70f2677213b021a968d00f4fda9927dc8a877ff8 --strategy-option theirs - - -git cherry-pick 1ad9a7275759845885ade59b86bec604da8294a4 --strategy-option theirs - - -git cherry-pick 3c35cbf750f28efb088ceb488ffec7c5c7e4e052 --strategy-option theirs - - -git cherry-pick c9292e548cd53c6388b71fdbd64f999337cfb848 --strategy-option theirs - - -git cherry-pick 71bfe79f3be55980737ff3152f197c750073b585 --strategy-option theirs - - -git cherry-pick 52723a5814d66ff073cbc125ea00ac666f34f65b --strategy-option theirs - - -git cherry-pick dacf0c2a6cabf088b0f17f4eca57e01c466286c0 --strategy-option theirs - - -git cherry-pick 991d24bad21ccf4b8350cba2b2ed3ceca6d90cea --strategy-option theirs - - -git cherry-pick b409e2eb50aec6699d9fa61307d1d3b945544782 --strategy-option theirs - - -git cherry-pick 231ab177b8c58c4389056fd205b4df9433cbb4b1 --strategy-option theirs - - -git cherry-pick a85f7a536193834f8d6a3ab0aaf5e3c8ed6d9009 --strategy-option theirs - -git cherry-pick ade05d911c4667e9ec04bc31322e911a13eba391 --strategy-option theirs - - -git cherry-pick 16271f55563db40032e9abb81cc7819965c35232 --strategy-option theirs - - -git cherry-pick c385d498874d4ca34f454e3cb9ad9e4c0e3219ae --strategy-option theirs - - -git cherry-pick 66742934a495ac0095854006169c3c6dada0d68f --strategy-option theirs - - -git cherry-pick 6b3eb50e6ace45eb0310f6ee99e6083425c9a43d --strategy-option theirs - - -git cherry-pick 3042c1115c9f5e3731dc94a95a559e4fb1a6047a --strategy-option theirs - - -git cherry-pick 794366f41590dd609afeea24794db7c029360090 --strategy-option theirs - - -git cherry-pick 0d614dc16593ab3810ff4589019e253c6d38eaf8 --strategy-option theirs - - -git cherry-pick f69faccb9ddd393662fac08ccc3dd284c22feff6 --strategy-option theirs - - -git cherry-pick 2763514508d58e72834bb285a77411c6000dd943 --strategy-option theirs - - -git cherry-pick 7bdfcf1afc29cf35f1d408063d7422bac8166f7a --strategy-option theirs - - -git cherry-pick 1b62981a1a51e4edcaad538fb3c26e3ed1de2b17 --strategy-option theirs - - -git cherry-pick 4732d4a7322433636d8736d53a30cd7ee9b0e4ed --strategy-option theirs - - -git cherry-pick 0e3853a00fce83339058421b807587bcf622e79e --strategy-option theirs - - -git cherry-pick 21d7bc8391169cdf62006c647472823f7d37205f --strategy-option theirs \ No newline at end of file From 45bd346ac576aad85a8ee08a43346cf603a5eabe Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Wed, 20 Oct 2021 10:25:03 +0200 Subject: [PATCH 80/93] Fix kibanaVersion dep --- .../client_integration/helpers/app_context.mock.ts | 10 +++++----- .../client_integration/helpers/setup_environment.tsx | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts index 8f142dcdb4b6d..3fa6be18a9b31 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts @@ -5,6 +5,7 @@ * 2.0. */ +import SemVer from 'semver/classes/semver'; import { deprecationsServiceMock, docLinksServiceMock, @@ -16,7 +17,6 @@ import { } from 'src/core/public/mocks'; import { sharePluginMock } from 'src/plugins/share/public/mocks'; -import { mockKibanaSemverVersion } from '../../../common/constants'; import { apiService } from '../../../public/application/lib/api'; import { breadcrumbService } from '../../../public/application/lib/breadcrumbs'; import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; @@ -53,12 +53,12 @@ shareMock.url.locators.get = (id: IdKey) => ({ `${idToUrlMap[id]}?${stringifySearchParams(params)}`, }); -export const getAppContextMock = () => ({ +export const getAppContextMock = (kibanaVersion: SemVer) => ({ isReadOnlyMode: false, kibanaVersionInfo: { - currentMajor: mockKibanaSemverVersion.major, - prevMajor: mockKibanaSemverVersion.major - 1, - nextMajor: mockKibanaSemverVersion.major + 1, + currentMajor: kibanaVersion.major, + prevMajor: kibanaVersion.major - 1, + nextMajor: kibanaVersion.major + 1, }, services: { ...servicesMock, diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx index 8e08ab380ceaf..0e4af0b697a49 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/setup_environment.tsx @@ -43,7 +43,7 @@ export const WithAppDependencies = apiService.setup(mockHttpClient as unknown as HttpSetup); breadcrumbService.setup(() => ''); - const appContextMock = getAppContextMock() as unknown as AppDependencies; + const appContextMock = getAppContextMock(kibanaVersion) as unknown as AppDependencies; return ( Date: Wed, 20 Oct 2021 12:29:56 +0200 Subject: [PATCH 81/93] Updated config.ts to fix UA test UA functional API integration test to check cloud backup status creates a snapshot repo, which fails to be created with my changes to config.ts `'path.repo=/tmp/repo,/tmp/repo_1,/tmp/repo_2,'`. Adding `/tmp/cloud-snapshots/'` to the config fixes the test. --- x-pack/test/api_integration/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index 678f7a0d3d929..66eaf17b09441 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -41,7 +41,7 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi serverArgs: [ ...xPackFunctionalTestsConfig.get('esTestCluster.serverArgs'), 'node.attr.name=apiIntegrationTestNode', - 'path.repo=/tmp/repo,/tmp/repo_1,/tmp/repo_2', + 'path.repo=/tmp/repo,/tmp/repo_1,/tmp/repo_2,/tmp/cloud-snapshots/', ], }, }; From cd2be507a50abd6420a0d6379f6ed6201c2bdd22 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 25 Oct 2021 11:26:42 +0200 Subject: [PATCH 82/93] Address CR changes --- .../client_integration/kibana_deprecations/service.mock.ts | 2 +- .../reindex/flyout/checklist_step.test.tsx | 5 +++++ .../deprecation_types/reindex/flyout/warning_step.test.tsx | 6 ------ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts index dc8bfdddf1964..6a3d376acecab 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/kibana_deprecations/service.mock.ts @@ -22,7 +22,7 @@ const kibanaDeprecations: DomainDeprecationDetails[] = [ title: 'Test deprecation title 1', message: 'Test deprecation message 1', deprecationType: 'config', - configPath: 'path', + configPath: 'test', }, { correctiveActions: { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx index c68f580494b29..705b4aa906bff 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx @@ -40,6 +40,11 @@ describe('ChecklistFlyout', () => { onConfirmInputChange: jest.fn(), startReindex: jest.fn(), cancelReindex: jest.fn(), + http: { + basePath: { + prepend: jest.fn(), + }, + } as any, renderGlobalCallouts: jest.fn(), reindexState: { loadingState: LoadingState.Success, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx index 11caed5e03a66..35e4a4b0b843f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx @@ -16,11 +16,6 @@ import { MAJOR_VERSION } from '../../../../../../../common/constants'; import { idForWarning, WarningsFlyoutStep } from './warnings_step'; const kibanaVersion = new SemVer(MAJOR_VERSION); -const mockKibanaVersionInfo = { - currentMajor: kibanaVersion.major, - prevMajor: kibanaVersion.major - 1, - nextMajor: kibanaVersion.major + 1, -}; jest.mock('../../../../../app_context', () => { const { docLinksServiceMock } = jest.requireActual( @@ -30,7 +25,6 @@ jest.mock('../../../../../app_context', () => { return { useAppContext: () => { return { - kibanaVersionInfo: mockKibanaVersionInfo, services: { core: { docLinks: docLinksServiceMock.createStartContract(), From 145cad0df68e27453f6ae5261f24f21868de7024 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 26 Oct 2021 12:29:52 +0100 Subject: [PATCH 83/93] Add missing error handler for system indices migration (#116088) --- .../migrate_system_indices.test.tsx | 31 +++++++++++ .../plugins/upgrade_assistant/common/types.ts | 6 +++ .../migrate_system_indices.tsx | 52 +++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx index f6c69c818b378..e3f6d747deaed 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/migrate_system_indices/migrate_system_indices.test.tsx @@ -132,5 +132,36 @@ describe('Overview - Migrate system indices', () => { expect(exists('startSystemIndicesMigrationButton')).toBe(true); expect(find('startSystemIndicesMigrationButton').props().disabled).toBe(false); }); + + test('Handles errors from migration', async () => { + httpRequestsMockHelpers.setLoadSystemIndicesMigrationStatus({ + migration_status: 'ERROR', + features: [ + { + feature_name: 'kibana', + indices: [ + { + index: '.kibana', + migration_status: 'ERROR', + failure_cause: { + error: { + type: 'mapper_parsing_exception', + }, + }, + }, + ], + }, + ], + }); + + testBed = await setupOverviewPage(); + + const { exists } = testBed; + + // Error is displayed + expect(exists('migrationFailedCallout')).toBe(true); + // CTA is enabled + expect(exists('startSystemIndicesMigrationButton')).toBe(true); + }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 0de19630bcebd..89afa05dfe222 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -239,6 +239,12 @@ export interface SystemIndicesMigrationFeature { indices: Array<{ index: string; version: string; + failure_cause?: { + error: { + type: string; + reason: string; + }; + }; }>; } export interface SystemIndicesMigrationStatus { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx index e54568117789a..d14958148b2f8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/migrate_system_indices/migrate_system_indices.tsx @@ -8,6 +8,7 @@ import React, { FunctionComponent, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiText, EuiButton, @@ -17,9 +18,11 @@ import { EuiCallOut, EuiFlexGroup, EuiFlexItem, + EuiCode, } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; +import type { SystemIndicesMigrationFeature } from '../../../../../common/types'; import type { OverviewStepProps } from '../../types'; import { useMigrateSystemIndices } from './use_migrate_system_indices'; @@ -27,6 +30,20 @@ interface Props { setIsComplete: OverviewStepProps['setIsComplete']; } +const getFailureCause = (features: SystemIndicesMigrationFeature[]) => { + const featureWithError = features.find((feature) => feature.migration_status === 'ERROR'); + + if (featureWithError) { + const indexWithError = featureWithError.indices.find((index) => index.failure_cause); + return { + feature: featureWithError?.feature_name, + failureCause: indexWithError?.failure_cause?.error.type, + }; + } + + return {}; +}; + const i18nTexts = { title: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.title', { defaultMessage: 'Migrate system indices', @@ -67,6 +84,26 @@ const i18nTexts = { loadingError: i18n.translate('xpack.upgradeAssistant.overview.systemIndices.loadingError', { defaultMessage: 'Could not retrieve the system indices status', }), + migrationFailedTitle: i18n.translate( + 'xpack.upgradeAssistant.overview.systemIndices.migrationFailedTitle', + { + defaultMessage: 'System indices migration failed', + } + ), + migrationFailedBody: (features: SystemIndicesMigrationFeature[]) => { + const { feature, failureCause } = getFailureCause(features); + + return ( + {failureCause}, + }} + /> + ); + }, }; const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) => { @@ -137,6 +174,21 @@ const MigrateSystemIndicesStep: FunctionComponent = ({ setIsComplete }) = )} + {migrationStatus.data?.migration_status === 'ERROR' && ( + <> + +

{i18nTexts.migrationFailedBody(migrationStatus.data?.features)}

+
+ + + )} + Date: Tue, 26 Oct 2021 18:36:12 +0200 Subject: [PATCH 84/93] Fix broken tests --- .../routes/reindex_indices/batch_reindex_indices.ts | 4 ++-- .../server/routes/reindex_indices/reindex_indices.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts index 732eedd6c3605..62be9a1807aad 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/batch_reindex_indices.ts @@ -6,7 +6,7 @@ */ import { schema } from '@kbn/config-schema'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { API_BASE_PATH } from '../../../common/constants'; import { ReindexStatus } from '../../../common/types'; @@ -62,7 +62,7 @@ export function registerBatchReindexIndicesRoutes( body: result, }); } catch (error) { - if (error instanceof ResponseError) { + if (error instanceof errors.ResponseError) { return handleEsError({ error, response }); } return mapAnyErrorToKibanaHttpResponse(error); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts index f5fefe55379c7..30f7c77cf73ab 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts @@ -6,7 +6,7 @@ */ import { schema } from '@kbn/config-schema'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { API_BASE_PATH } from '../../../common/constants'; import { versionCheckHandlerWrapper } from '../../lib/es_version_precheck'; @@ -70,7 +70,7 @@ export function registerReindexIndicesRoutes( body: result, }); } catch (error) { - if (error instanceof ResponseError) { + if (error instanceof errors.ResponseError) { return handleEsError({ error, response }); } return mapAnyErrorToKibanaHttpResponse(error); @@ -122,7 +122,7 @@ export function registerReindexIndicesRoutes( }, }); } catch (error) { - if (error instanceof ResponseError) { + if (error instanceof errors.ResponseError) { return handleEsError({ error, response }); } return mapAnyErrorToKibanaHttpResponse(error); @@ -168,7 +168,7 @@ export function registerReindexIndicesRoutes( return response.ok({ body: { acknowledged: true } }); } catch (error) { - if (error instanceof ResponseError) { + if (error instanceof errors.ResponseError) { return handleEsError({ error, response }); } From 03a32e85e00675dfde59bd121cece31d3afd59bf Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 26 Oct 2021 18:46:48 +0200 Subject: [PATCH 85/93] Fix test --- .../server/lib/reindexing/reindex_service.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index bc66c63471656..65d34ed1d11cb 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -509,7 +509,7 @@ describe('reindexService', () => { // Original index should have been set back to allow reads. expect(clusterClient.asCurrentUser.indices.putSettings).toHaveBeenCalledWith({ index: 'myIndex', - body: { settings: { blocks: { write: false } } }, + body: { blocks: { write: false } }, }); }); }); From c873873ff0b58ea9031505a99f9fae058881664e Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 26 Oct 2021 18:47:55 +0200 Subject: [PATCH 86/93] Skip tests --- .../test/functional/apps/upgrade_assistant/overview_page.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts index c1549055e4550..45e4a8c7ff830 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts @@ -17,7 +17,7 @@ export default function upgradeAssistantOverviewPageFunctionalTests({ const testSubjects = getService('testSubjects'); const es = getService('es'); - describe('Overview Page', function () { + describe.skip('Overview Page', function () { this.tags('skipFirefox'); before(async () => { @@ -38,14 +38,14 @@ export default function upgradeAssistantOverviewPageFunctionalTests({ }); }); - it.skip('Should render all steps', async () => { + it('Should render all steps', async () => { testSubjects.exists('backupStep-incomplete'); testSubjects.exists('fixIssuesStep-incomplete'); testSubjects.exists('fixLogsStep-incomplete'); testSubjects.exists('upgradeStep'); }); - describe.skip('fixLogsStep', () => { + describe('fixLogsStep', () => { before(async () => { // Access to system indices will be deprecated and should generate a deprecation log await es.indices.get({ index: '.kibana' }); From 6d4e086b7342b61f818909298690ba52094032f2 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 26 Oct 2021 20:27:51 +0200 Subject: [PATCH 87/93] Fix linter errors and import --- .../lib/reindexing/reindex_service.test.ts | 21 +++---------------- .../upgrade_assistant/deprecation_pages.ts | 1 - 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index 65d34ed1d11cb..33b2148811ecc 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -7,7 +7,7 @@ jest.mock('../es_indices_state_check', () => ({ esIndicesStateCheck: jest.fn() })); import { BehaviorSubject } from 'rxjs'; -import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; +import { TransportResult } from '@elastic/elasticsearch'; import { Logger } from 'src/core/server'; import { elasticsearchServiceMock, loggingSystemMock } from 'src/core/server/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths @@ -29,10 +29,10 @@ import { versionService } from '../version'; import { ReindexService, reindexServiceFactory } from './reindex_service'; -const asApiResponse = (body: T): RequestEvent => +const asApiResponse = (body: T): TransportResult => ({ body, - } as RequestEvent); + } as TransportResult); const { currentMajor, prevMajor } = getMockVersionInfo(); @@ -96,7 +96,6 @@ describe('reindexService', () => { it('calls security API with basic requirements', async () => { clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ has_all_requested: true }) ); @@ -122,7 +121,6 @@ describe('reindexService', () => { it('includes checking for permissions on the baseName which could be an alias', async () => { clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ has_all_requested: true }) ); @@ -383,7 +381,6 @@ describe('reindexService', () => { }, } as any); - // @ts-expect-error not full interface clusterClient.asCurrentUser.tasks.cancel.mockResolvedValueOnce(asApiResponse(true)); await service.cancelReindexing('myIndex'); @@ -456,7 +453,6 @@ describe('reindexService', () => { it('creates new index with settings and mappings and updates lastCompletedStep', async () => { actions.getFlatSettings.mockResolvedValueOnce(settingsMappings); clusterClient.asCurrentUser.indices.create.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ acknowledged: true }) ); const updatedOp = await service.processNextStep(reindexOp); @@ -473,12 +469,10 @@ describe('reindexService', () => { it('fails if create index is not acknowledged', async () => { clusterClient.asCurrentUser.indices.get.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ myIndex: settingsMappings }) ); clusterClient.asCurrentUser.indices.create.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ acknowledged: false }) ); const updatedOp = await service.processNextStep(reindexOp); @@ -490,7 +484,6 @@ describe('reindexService', () => { it('fails if create index fails', async () => { clusterClient.asCurrentUser.indices.get.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ myIndex: settingsMappings }) ); @@ -569,7 +562,6 @@ describe('reindexService', () => { describe('reindex task is not complete', () => { it('updates reindexTaskPercComplete', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ completed: false, task: { status: { created: 10, total: 100 } }, @@ -585,7 +577,6 @@ describe('reindexService', () => { describe('reindex task is complete', () => { it('deletes task, updates reindexTaskPercComplete, updates lastCompletedStep', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ completed: true, task: { status: { created: 100, total: 100 } }, @@ -593,14 +584,12 @@ describe('reindexService', () => { ); clusterClient.asCurrentUser.count.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ count: 100, }) ); clusterClient.asCurrentUser.delete.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ result: 'deleted', }) @@ -617,7 +606,6 @@ describe('reindexService', () => { it('fails if docs created is less than count in source index', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ completed: true, task: { status: { created: 95, total: 95 } }, @@ -625,7 +613,6 @@ describe('reindexService', () => { ); clusterClient.asCurrentUser.count.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ count: 100, }) @@ -642,7 +629,6 @@ describe('reindexService', () => { describe('reindex task is cancelled', () => { it('deletes task, updates status to cancelled', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( - // @ts-expect-error not full interface asApiResponse({ completed: true, task: { status: { created: 100, total: 100, canceled: 'by user request' } }, @@ -650,7 +636,6 @@ describe('reindexService', () => { ); clusterClient.asCurrentUser.delete.mockResolvedValue( - // @ts-expect-error not full interface asApiResponse({ result: 'deleted' }) ); diff --git a/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts index a32a795ee0960..ab989b0dabb83 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts @@ -50,7 +50,6 @@ export default function upgradeAssistantFunctionalTests({ }: FtrProviderContext) { const PageObjects = getPageObjects(['upgradeAssistant', 'common']); const retry = getService('retry'); - const security = getService('security'); const testSubjects = getService('testSubjects'); const es = getService('es'); const security = getService('security'); From 41932b901a04cda94089bbf66adc83d6fa646748 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 2 Nov 2021 15:20:55 +0100 Subject: [PATCH 88/93] [Upgrade Assistant] Fix typo in retrieval of cluster settings (#116335) * Fix typos * Fix typo also in server tests * Make sure log collection remains enabled throughout the test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/es_deprecation_logging_apis.test.ts | 12 ++++++------ .../server/lib/es_deprecation_logging_apis.ts | 4 ++-- .../server/routes/deprecation_logging.test.ts | 4 ++-- .../apps/upgrade_assistant/overview_page.ts | 11 +++++++++-- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts index 0e01d8d6a3458..b3b93582e2260 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts @@ -64,7 +64,7 @@ describe('setDeprecationLogging', () => { }); describe('isDeprecationLoggingEnabled', () => { - ['default', 'persistent', 'transient'].forEach((tier) => { + ['defaults', 'persistent', 'transient'].forEach((tier) => { ['ALL', 'TRACE', 'DEBUG', 'INFO', 'WARN', 'ALL'].forEach((level) => { it(`returns true when ${tier} is set to ${level}`, () => { expect(isDeprecationLoggingEnabled({ [tier]: { logger: { deprecation: level } } })).toBe( @@ -74,7 +74,7 @@ describe('isDeprecationLoggingEnabled', () => { }); }); - ['default', 'persistent', 'transient'].forEach((tier) => { + ['defaults', 'persistent', 'transient'].forEach((tier) => { ['ERROR', 'FATAL'].forEach((level) => { it(`returns false when ${tier} is set to ${level}`, () => { expect(isDeprecationLoggingEnabled({ [tier]: { logger: { deprecation: level } } })).toBe( @@ -87,7 +87,7 @@ describe('isDeprecationLoggingEnabled', () => { it('allows transient to override persistent and default', () => { expect( isDeprecationLoggingEnabled({ - default: { logger: { deprecation: 'FATAL' } }, + defaults: { logger: { deprecation: 'FATAL' } }, persistent: { logger: { deprecation: 'FATAL' } }, transient: { logger: { deprecation: 'WARN' } }, }) @@ -97,7 +97,7 @@ describe('isDeprecationLoggingEnabled', () => { it('allows persistent to override default', () => { expect( isDeprecationLoggingEnabled({ - default: { logger: { deprecation: 'FATAL' } }, + defaults: { logger: { deprecation: 'FATAL' } }, persistent: { logger: { deprecation: 'WARN' } }, }) ).toBe(true); @@ -108,7 +108,7 @@ describe('isDeprecationLogIndexingEnabled', () => { it('allows transient to override persistent and default', () => { expect( isDeprecationLogIndexingEnabled({ - default: { cluster: { deprecation_indexing: { enabled: 'false' } } }, + defaults: { cluster: { deprecation_indexing: { enabled: 'false' } } }, persistent: { cluster: { deprecation_indexing: { enabled: 'false' } } }, transient: { cluster: { deprecation_indexing: { enabled: 'true' } } }, }) @@ -118,7 +118,7 @@ describe('isDeprecationLogIndexingEnabled', () => { it('allows persistent to override default', () => { expect( isDeprecationLogIndexingEnabled({ - default: { cluster: { deprecation_indexing: { enabled: 'false' } } }, + defaults: { cluster: { deprecation_indexing: { enabled: 'false' } } }, persistent: { cluster: { deprecation_indexing: { enabled: 'true' } } }, }) ).toBe(true); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts index 214aabb989921..2793c2c6ac818 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts @@ -51,7 +51,7 @@ export async function setDeprecationLogging( } export function isDeprecationLogIndexingEnabled(settings: any) { - const clusterDeprecationLoggingEnabled = ['default', 'persistent', 'transient'].reduce( + const clusterDeprecationLoggingEnabled = ['defaults', 'persistent', 'transient'].reduce( (currentLogLevel, settingsTier) => get(settings, [settingsTier, 'cluster', 'deprecation_indexing', 'enabled'], currentLogLevel), 'false' @@ -61,7 +61,7 @@ export function isDeprecationLogIndexingEnabled(settings: any) { } export function isDeprecationLoggingEnabled(settings: any) { - const deprecationLogLevel = ['default', 'persistent', 'transient'].reduce( + const deprecationLogLevel = ['defaults', 'persistent', 'transient'].reduce( (currentLogLevel, settingsTier) => get(settings, [settingsTier, 'logger', 'deprecation'], currentLogLevel), 'WARN' diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts index fc61832e69c12..89d4e4cb398c6 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts @@ -45,7 +45,7 @@ describe('deprecation logging API', () => { .getSettings as jest.Mock ).mockResolvedValue({ body: { - default: { + defaults: { cluster: { deprecation_indexing: { enabled: 'true' } }, }, }, @@ -84,7 +84,7 @@ describe('deprecation logging API', () => { .putSettings as jest.Mock ).mockResolvedValue({ body: { - default: { + defaults: { logger: { deprecation: 'WARN' }, cluster: { deprecation_indexing: { enabled: 'true' } }, }, diff --git a/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts index 45e4a8c7ff830..0b8d15695689a 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/overview_page.ts @@ -47,16 +47,23 @@ export default function upgradeAssistantOverviewPageFunctionalTests({ describe('fixLogsStep', () => { before(async () => { + await PageObjects.upgradeAssistant.navigateToPage(); // Access to system indices will be deprecated and should generate a deprecation log await es.indices.get({ index: '.kibana' }); - - await PageObjects.upgradeAssistant.clickDeprecationLoggingToggle(); + // Only click deprecation logging toggle if its not already enabled + if (!(await testSubjects.isDisplayed('externalLinksTitle'))) { + await PageObjects.upgradeAssistant.clickDeprecationLoggingToggle(); + } await retry.waitFor('UA external links title to be present', async () => { return testSubjects.isDisplayed('externalLinksTitle'); }); }); + beforeEach(async () => { + await PageObjects.upgradeAssistant.navigateToPage(); + }); + it('Shows warnings callout if there are deprecations', async () => { testSubjects.exists('hasWarningsCallout'); }); From a43943f8655739af0c210889ae4e3e8030d534cf Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 8 Nov 2021 10:54:23 +0100 Subject: [PATCH 89/93] Fix type errors --- .../__jest__/client_integration/helpers/index.ts | 2 +- .../upgrade_assistant/public/shared_imports.ts | 9 +++------ .../server/lib/reindexing/reindex_service.test.ts | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts index 899950c871fb6..f70bfd00e9c07 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/index.ts @@ -6,4 +6,4 @@ */ export { setupEnvironment, WithAppDependencies, kibanaVersion } from './setup_environment'; -export { advanceTime } from './time_manipulation'; \ No newline at end of file +export { advanceTime } from './time_manipulation'; diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index aada603dc9e73..d3ef467917288 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -5,12 +5,6 @@ * 2.0. */ -export { - sendRequest, - SendRequestConfig, - SendRequestResponse, - UseRequestConfig, -} from '../../../../src/plugins/es_ui_shared/public/'; export { sendRequest, useRequest, @@ -19,6 +13,9 @@ export { WithPrivileges, Privileges, MissingPrivileges, + SendRequestConfig, + SendRequestResponse, + UseRequestConfig, AuthorizationProvider, AuthorizationContext, Authorization, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index 33b2148811ecc..b68faf7f75b99 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -96,6 +96,7 @@ describe('reindexService', () => { it('calls security API with basic requirements', async () => { clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ has_all_requested: true }) ); @@ -121,6 +122,7 @@ describe('reindexService', () => { it('includes checking for permissions on the baseName which could be an alias', async () => { clusterClient.asCurrentUser.security.hasPrivileges.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ has_all_requested: true }) ); @@ -381,6 +383,7 @@ describe('reindexService', () => { }, } as any); + // @ts-expect-error not full interface clusterClient.asCurrentUser.tasks.cancel.mockResolvedValueOnce(asApiResponse(true)); await service.cancelReindexing('myIndex'); @@ -453,6 +456,7 @@ describe('reindexService', () => { it('creates new index with settings and mappings and updates lastCompletedStep', async () => { actions.getFlatSettings.mockResolvedValueOnce(settingsMappings); clusterClient.asCurrentUser.indices.create.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ acknowledged: true }) ); const updatedOp = await service.processNextStep(reindexOp); @@ -469,10 +473,12 @@ describe('reindexService', () => { it('fails if create index is not acknowledged', async () => { clusterClient.asCurrentUser.indices.get.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ myIndex: settingsMappings }) ); clusterClient.asCurrentUser.indices.create.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ acknowledged: false }) ); const updatedOp = await service.processNextStep(reindexOp); @@ -484,6 +490,7 @@ describe('reindexService', () => { it('fails if create index fails', async () => { clusterClient.asCurrentUser.indices.get.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ myIndex: settingsMappings }) ); @@ -562,6 +569,7 @@ describe('reindexService', () => { describe('reindex task is not complete', () => { it('updates reindexTaskPercComplete', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ completed: false, task: { status: { created: 10, total: 100 } }, @@ -577,6 +585,7 @@ describe('reindexService', () => { describe('reindex task is complete', () => { it('deletes task, updates reindexTaskPercComplete, updates lastCompletedStep', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ completed: true, task: { status: { created: 100, total: 100 } }, @@ -584,12 +593,14 @@ describe('reindexService', () => { ); clusterClient.asCurrentUser.count.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ count: 100, }) ); clusterClient.asCurrentUser.delete.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ result: 'deleted', }) @@ -606,6 +617,7 @@ describe('reindexService', () => { it('fails if docs created is less than count in source index', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ completed: true, task: { status: { created: 95, total: 95 } }, @@ -613,6 +625,7 @@ describe('reindexService', () => { ); clusterClient.asCurrentUser.count.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ count: 100, }) @@ -629,6 +642,7 @@ describe('reindexService', () => { describe('reindex task is cancelled', () => { it('deletes task, updates status to cancelled', async () => { clusterClient.asCurrentUser.tasks.get.mockResolvedValueOnce( + // @ts-expect-error not full interface asApiResponse({ completed: true, task: { status: { created: 100, total: 100, canceled: 'by user request' } }, @@ -636,6 +650,7 @@ describe('reindexService', () => { ); clusterClient.asCurrentUser.delete.mockResolvedValue( + // @ts-expect-error not full interface asApiResponse({ result: 'deleted' }) ); From 69d6a517b28a01f23e5fb5b015bd779cb181d38a Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 8 Nov 2021 11:01:41 +0100 Subject: [PATCH 90/93] Fix integration test types --- .../upgrade_assistant/cloud_backup_status.ts | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts b/x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts index 7095c115ae7e1..b1a4d7e8b0475 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/cloud_backup_status.ts @@ -16,18 +16,16 @@ export default function ({ getService }: FtrProviderContext) { const CLOUD_SNAPSHOT_REPOSITORY = 'found-snapshots'; const createCloudRepository = () => { - return es.snapshot - .createRepository({ - repository: CLOUD_SNAPSHOT_REPOSITORY, - body: { - type: 'fs', - settings: { - location: '/tmp/cloud-snapshots/', - }, + return es.snapshot.createRepository({ + name: CLOUD_SNAPSHOT_REPOSITORY, + body: { + type: 'fs', + settings: { + location: '/tmp/cloud-snapshots/', }, - verify: false, - }) - .then(({ body }) => body); + }, + verify: false, + }); }; const createCloudSnapshot = (snapshotName: string) => { @@ -60,7 +58,7 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { await createCloudRepository(); await createCloudSnapshot('test_snapshot_1'); - mostRecentSnapshot = (await createCloudSnapshot('test_snapshot_2')).body.snapshot; + mostRecentSnapshot = (await createCloudSnapshot('test_snapshot_2')).snapshot; }); after(async () => { From 5c2845bb046f00dce43063a71ccef818e0551eb5 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 8 Nov 2021 11:34:05 +0100 Subject: [PATCH 91/93] Fix accessibility test type errors --- x-pack/test/accessibility/apps/upgrade_assistant.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 72899854f4b30..2c0e81a6fb831 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { IndicesCreateRequest } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FtrProviderContext } from '../ftr_provider_context'; -const translogSettingsIndexDeprecation: IndicesCreateRequest = { +const translogSettingsIndexDeprecation: estypes.IndicesCreateRequest = { index: 'deprecated_settings', body: { settings: { @@ -19,7 +19,7 @@ const translogSettingsIndexDeprecation: IndicesCreateRequest = { }, }; -const multiFieldsIndexDeprecation: IndicesCreateRequest = { +const multiFieldsIndexDeprecation: estypes.IndicesCreateRequest = { index: 'nested_multi_fields', body: { mappings: { From db0b8471ad57041fca9994c216b4419a5783d716 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 8 Nov 2021 11:39:46 +0100 Subject: [PATCH 92/93] Fix linter errors in shared_imports --- .../upgrade_assistant/public/shared_imports.ts | 14 ++++++++------ .../upgrade_assistant/server/shared_imports.ts | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index d3ef467917288..c6c00f34bfadf 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -5,20 +5,22 @@ * 2.0. */ +export type { + SendRequestConfig, + SendRequestResponse, + UseRequestConfig, + Privileges, + MissingPrivileges, + Authorization, +} from '../../../../src/plugins/es_ui_shared/public/'; export { sendRequest, useRequest, SectionLoading, GlobalFlyout, WithPrivileges, - Privileges, - MissingPrivileges, - SendRequestConfig, - SendRequestResponse, - UseRequestConfig, AuthorizationProvider, AuthorizationContext, - Authorization, } from '../../../../src/plugins/es_ui_shared/public/'; export { Storage } from '../../../../src/plugins/kibana_utils/public'; diff --git a/x-pack/plugins/upgrade_assistant/server/shared_imports.ts b/x-pack/plugins/upgrade_assistant/server/shared_imports.ts index 3193c0b4b54a0..1c43f89469ac1 100644 --- a/x-pack/plugins/upgrade_assistant/server/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/server/shared_imports.ts @@ -6,4 +6,4 @@ */ export { handleEsError } from '../../../../src/plugins/es_ui_shared/server'; -export { Privileges } from '../../../../src/plugins/es_ui_shared/common'; +export type { Privileges } from '../../../../src/plugins/es_ui_shared/common'; From 2c629dddf6b3dfc0f824d967e147ca6872137bc1 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Mon, 8 Nov 2021 12:39:30 +0100 Subject: [PATCH 93/93] Fix functional test types --- .../functional/apps/upgrade_assistant/deprecation_pages.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts index ab989b0dabb83..3024f8a5a7208 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/deprecation_pages.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { IndicesCreateRequest } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FtrProviderContext } from '../../ftr_provider_context'; -const multiFieldsIndexDeprecation: IndicesCreateRequest = { +const multiFieldsIndexDeprecation: estypes.IndicesCreateRequest = { index: 'nested_multi_fields', body: { mappings: { @@ -33,7 +33,7 @@ const multiFieldsIndexDeprecation: IndicesCreateRequest = { }, }; -const translogSettingsIndexDeprecation: IndicesCreateRequest = { +const translogSettingsIndexDeprecation: estypes.IndicesCreateRequest = { index: 'deprecated_settings', body: { settings: {