From 326933a3e5087b3066324859e270a23de7c82614 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Thu, 19 Oct 2023 09:10:34 +0200 Subject: [PATCH 1/3] [Security Solution] Unskip urls/not_found Serverless Cypress tests (#169243) **Addresses:** https://github.com/elastic/kibana/issues/161540 ## Summary This PR unskips `urls/not_found.cy.ts` Serverless Cypress tests. ## Flaky test runner `urls/not_found.cy.ts` [150 runs](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/3590) --- .../security_solution_cypress/cypress/e2e/urls/not_found.cy.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/urls/not_found.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/urls/not_found.cy.ts index b257e340bd7cbc..329e0b33144bf2 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/urls/not_found.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/urls/not_found.cy.ts @@ -25,8 +25,7 @@ import { editRuleUrl } from '../../urls/edit_rule'; const mockRuleId = '5a4a0460-d822-11eb-8962-bfd4aff0a9b3'; -// FLAKY: https://github.com/elastic/kibana/issues/165710 -describe('Display not found page', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { +describe('Display not found page', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); visitWithTimeRange(TIMELINES_URL); From 662265dc50fd59eb77110c67eb2a23b94130b038 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 19 Oct 2023 10:21:58 +0300 Subject: [PATCH 2/3] [Discover] Fixes sorting for ES|QL columns that do not exist on a dataview (#169240) ## Summary Closes https://github.com/elastic/kibana/issues/168118 Fixes the broken sorting of columns that are created from the query and they do not exist on the dataview. This was working correctly so I assume is a regression from a refactoring. image ### Checklist - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Julia Rechkunova --- .../data_table_columns.test.tsx.snap | 4 +- .../components/data_table_columns.test.tsx | 60 +++++++++++++++++++ .../src/components/data_table_columns.tsx | 4 +- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap b/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap index 253289db871776..d5cbd1a0d408e8 100644 --- a/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap +++ b/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap @@ -956,7 +956,7 @@ Array [ "displayAsText": "extension", "id": "extension", "isSortable": false, - "schema": "string", + "schema": "numeric", "visibleCellActions": undefined, }, Object { @@ -1272,7 +1272,7 @@ Array [ "displayAsText": "message", "id": "message", "isSortable": false, - "schema": "string", + "schema": "kibana-json", "visibleCellActions": undefined, }, ] diff --git a/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx index c46c676b48baa4..38cbdb5aeb63a6 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.test.tsx @@ -159,4 +159,64 @@ describe('Data table columns', function () { expect(actual).toMatchSnapshot(); }); }); + + describe('Textbased languages grid columns', () => { + it('returns eui grid with in memory sorting for text based languages and columns on the dataview', async () => { + const columnsNotInDataview = getVisibleColumns( + ['extension'], + dataViewWithTimefieldMock, + true + ) as string[]; + const gridColumns = getEuiGridColumns({ + columns: columnsNotInDataview, + settings: {}, + dataView: dataViewWithTimefieldMock, + defaultColumns: false, + isSortEnabled: true, + isPlainRecord: true, + valueToStringConverter: dataTableContextMock.valueToStringConverter, + rowsCount: 100, + services: { + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, + }, + hasEditDataViewPermission: () => + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + onFilter: () => {}, + columnTypes: { + var_test: 'number', + }, + }); + expect(gridColumns[1].schema).toBe('string'); + }); + + it('returns eui grid with in memory sorting for text based languages and columns not on the columnTypes', async () => { + const columnsNotInDataview = getVisibleColumns( + ['var_test'], + dataViewWithTimefieldMock, + true + ) as string[]; + const gridColumns = getEuiGridColumns({ + columns: columnsNotInDataview, + settings: {}, + dataView: dataViewWithTimefieldMock, + defaultColumns: false, + isSortEnabled: true, + isPlainRecord: true, + valueToStringConverter: dataTableContextMock.valueToStringConverter, + rowsCount: 100, + services: { + uiSettings: servicesMock.uiSettings, + toastNotifications: servicesMock.toastNotifications, + }, + hasEditDataViewPermission: () => + servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(), + onFilter: () => {}, + columnTypes: { + var_test: 'number', + }, + }); + expect(gridColumns[1].schema).toBe('numeric'); + }); + }); }); diff --git a/packages/kbn-unified-data-table/src/components/data_table_columns.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx index 13b740a0bc7038..274b1148df4eb7 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_columns.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx @@ -125,9 +125,11 @@ function buildEuiGridColumn({ : []; } + const columnType = columnTypes?.[columnName] ?? dataViewField?.type; + const column: EuiDataGridColumn = { id: columnName, - schema: getSchemaByKbnType(dataViewField?.type), + schema: getSchemaByKbnType(columnType), isSortable: isSortEnabled && (isPlainRecord || dataViewField?.sortable === true), display: showColumnTokens ? ( Date: Thu, 19 Oct 2023 09:31:35 +0200 Subject: [PATCH 3/3] [Infra UI] Add Features section to Infra settings (#168712) Closes https://github.com/elastic/kibana/issues/167062 ## Summary * Adds "Features" section to Infra settings screen * Hooks changes to `uiSettings` into existing form in order to use the current "Discard" and "Apply" buttons logic * Replaces usage of `uiSettings` with `settings.client` as `uiSettings` seems to be [deprecated](https://github.com/elastic/kibana/pull/154710. Observables exposed by `uiSettings` do not seem to work anymore. * Deletes the Hosts landing screen * Revives the logic for showing/hiding Hosts nav item depending on the settings toggle https://github.com/elastic/kibana/assets/793851/767e69cc-98b1-4fe9-93d9-f39c08ac5c83 ## How to test * Checkout locally and run in stateful mode * Go to Infra Setttings screen and make sure Features section is present * Make sure that the "Infrastructure Hosts view" toggle shows/hides the Hosts nav item * Make sure that "Infrastructure Hosts view" in "Anvanced Settings" is synced with the the one in Infra settings --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/infra/kibana.jsonc | 3 +- .../enable_hosts_view_page.tsx | 86 ----------- .../hosts_landing_beta_dark.svg | 9 -- .../hosts_landing_beta_light.svg | 9 -- .../metrics/hosts/hosts_landing_page.tsx | 92 ------------ .../infra/public/pages/metrics/index.tsx | 8 +- .../settings/features_configuration_panel.tsx | 57 +++++++ .../source_configuration_settings.tsx | 47 ++++-- x-pack/plugins/infra/public/plugin.ts | 139 +++++++++++------- x-pack/plugins/infra/tsconfig.json | 3 +- .../public/hooks/use_editable_settings.tsx | 13 +- .../translations/translations/fr-FR.json | 7 - .../translations/translations/ja-JP.json | 7 - .../translations/translations/zh-CN.json | 7 - .../test/functional/apps/infra/hosts_view.ts | 101 ------------- .../page_objects/infra_hosts_view.ts | 22 --- 16 files changed, 190 insertions(+), 420 deletions(-) delete mode 100644 x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/enable_hosts_view_page.tsx delete mode 100644 x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_dark.svg delete mode 100644 x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_light.svg delete mode 100644 x-pack/plugins/infra/public/pages/metrics/hosts/hosts_landing_page.tsx create mode 100644 x-pack/plugins/infra/public/pages/metrics/settings/features_configuration_panel.tsx diff --git a/x-pack/plugins/infra/kibana.jsonc b/x-pack/plugins/infra/kibana.jsonc index 439ccd061f0a48..a23b6eb9e8df17 100644 --- a/x-pack/plugins/infra/kibana.jsonc +++ b/x-pack/plugins/infra/kibana.jsonc @@ -45,7 +45,8 @@ "kibanaReact", "ml", "embeddable", - "controls" + "controls", + "advancedSettings" ] } } diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/enable_hosts_view_page.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/enable_hosts_view_page.tsx deleted file mode 100644 index eb7c5567397fd3..00000000000000 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/enable_hosts_view_page.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { ReactNode } from 'react'; -import { EuiPageTemplate, EuiImage, EuiSpacer } from '@elastic/eui'; -import { css } from '@emotion/react'; -import { useEuiBackgroundColor } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useTrackPageview } from '@kbn/observability-shared-plugin/public'; -import { useIsDarkMode } from '../../../../../hooks/use_is_dark_mode'; -import { MetricsPageTemplate } from '../../../page_template'; -import hostsLandingBetaLight from './hosts_landing_beta_light.svg'; -import hostsLandingBetaDark from './hosts_landing_beta_dark.svg'; -import { BetaBadge } from '../../../../../components/beta_badge'; - -interface Props { - actions?: ReactNode; -} - -export const EnableHostsViewPage = ({ actions }: Props) => { - const backgroundColor = useEuiBackgroundColor('subdued'); - const isDarkMode = useIsDarkMode(); - - useTrackPageview({ app: 'infra_metrics', path: 'hosts_feature_enable_landing_page' }); - useTrackPageview({ - app: 'infra_metrics', - path: 'hosts_feature_enable_landing_page', - delay: 15000, - }); - - return ( - - - {i18n.translate('xpack.infra.hostsViewPage.landing.introTitle', { - defaultMessage: 'Host Analysis', - })} - - } - alignment="center" - icon={ - - } - color="plain" - layout="horizontal" - body={ - <> - - -

- {i18n.translate('xpack.infra.hostsViewPage.landing.introMessage', { - defaultMessage: `Welcome to the 'Hosts' feature, now available in beta! With this powerful tool, - you can easily view and analyse your hosts and identify any issues so you address them quickly. - Get a detailed view of metrics for your hosts, see which ones are triggering the most alerts and filter - the hosts you want to analyse using any KQL filter and easy breakdowns such as cloud provider and - operating system.`, - })} -

-

- {i18n.translate('xpack.infra.hostsViewPage.landing.tryTheFeatureMessage', { - defaultMessage: `This is a beta version of the feature and we would love your - feedback as we continue to develop and improve it. To access the feature, - simply enable below (or reach out to your internal administrator if not available). - Don't miss out on this powerful feature - try it out today!`, - })} -

- - } - css={css` - background-color: ${backgroundColor}; - `} - actions={actions} - /> -
- ); -}; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_dark.svg b/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_dark.svg deleted file mode 100644 index 221076d4fe2903..00000000000000 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_dark.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_light.svg b/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_light.svg deleted file mode 100644 index 00d5aa123db8ea..00000000000000 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/enable_hosts_view_page/hosts_landing_beta_light.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hosts_landing_page.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/hosts_landing_page.tsx deleted file mode 100644 index efb170ff174a9f..00000000000000 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hosts_landing_page.tsx +++ /dev/null @@ -1,92 +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 { EuiButton, EuiCallOut } from '@elastic/eui'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { EuiLink } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { i18n } from '@kbn/i18n'; -import { enableInfrastructureHostsView } from '@kbn/observability-plugin/public'; -import useObservable from 'react-use/lib/useObservable'; -import { Observable } from 'rxjs'; -import { InfraClientStartDeps } from '../../../types'; -import { EnableHostsViewPage } from './components/enable_hosts_view_page/enable_hosts_view_page'; -import { HostsPage } from '.'; - -export const HostsLandingPage = () => { - const { - services: { uiSettings, application }, - } = useKibana(); - const canEditAdvancedSettings = application?.capabilities.advancedSettings.save; - const isHostViewEnabled = useObservable( - uiSettings?.get$(enableInfrastructureHostsView) ?? - new Observable((subs) => subs.next(false)) - ); - - if (isHostViewEnabled) { - return ; - } - - if (canEditAdvancedSettings) { - return ( - { - uiSettings?.set(enableInfrastructureHostsView, true); - }} - > - {i18n.translate('xpack.infra.hostsViewPage.landing.enableHostsView', { - defaultMessage: 'Enable hosts view', - })} - - } - /> - ); - } - - return ( - -

- {i18n.translate( - 'xpack.infra.hostsViewPage.landing.calloutReachOutToYourKibanaAdministrator', - { - defaultMessage: `Your user role doesn’t have sufficient privileges to enable this feature - please - reach out to your Kibana Administrator and ask them to visit this page to enable this feature.`, - } - )} -

-

- - {i18n.translate('xpack.infra.hostsViewPage.landing.learnMore', { - defaultMessage: 'Learn more', - })} - - ), - }} - /> -

- - } - /> - ); -}; diff --git a/x-pack/plugins/infra/public/pages/metrics/index.tsx b/x-pack/plugins/infra/public/pages/metrics/index.tsx index d0e41a68446a69..4f270758d6fd16 100644 --- a/x-pack/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/index.tsx @@ -11,9 +11,10 @@ import React, { useContext } from 'react'; import { Routes, Route } from '@kbn/shared-ux-router'; import { EuiErrorBoundary, EuiHeaderLinks, EuiHeaderLink } from '@elastic/eui'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useKibana, useUiSetting } from '@kbn/kibana-react-plugin/public'; import { HeaderMenuPortal, useLinkProps } from '@kbn/observability-shared-plugin/public'; import { ObservabilityAIAssistantActionMenuItem } from '@kbn/observability-ai-assistant-plugin/public'; +import { enableInfrastructureHostsView } from '@kbn/observability-plugin/common'; import { MetricsSourceConfigurationProperties } from '../../../common/metrics_sources'; import { HelpCenterContent } from '../../components/help_center_content'; import { useReadOnlyBadge } from '../../hooks/use_readonly_badge'; @@ -23,7 +24,6 @@ import { MetricsExplorerPage } from './metrics_explorer'; import { SnapshotPage } from './inventory_view'; import { NodeDetail } from './metric_detail'; import { MetricsSettingsPage } from './settings'; -import { HostsLandingPage } from './hosts/hosts_landing_page'; import { SourceLoadingPage } from '../../components/source_loading_page'; import { WaffleOptionsProvider } from './inventory_view/hooks/use_waffle_options'; import { WaffleTimeProvider } from './inventory_view/hooks/use_waffle_time'; @@ -37,6 +37,7 @@ import { CreateDerivedIndexPattern, useSourceContext } from '../../containers/me import { NotFoundPage } from '../404'; import { ReactQueryProvider } from '../../containers/react_query_provider'; import { usePluginConfig } from '../../containers/plugin_config_context'; +import { HostsPage } from './hosts'; const ADD_DATA_LABEL = i18n.translate('xpack.infra.metricsHeaderAddDataButtonLabel', { defaultMessage: 'Add data', @@ -46,6 +47,7 @@ export const InfrastructurePage = () => { const config = usePluginConfig(); const uiCapabilities = useKibana().services.application?.capabilities; const { setHeaderActionMenu, theme$ } = useContext(HeaderActionMenuContext); + const isHostsViewEnabled = useUiSetting(enableInfrastructureHostsView); const settingsTabTitle = i18n.translate('xpack.infra.metrics.settingsTabTitle', { defaultMessage: 'Settings', @@ -113,7 +115,7 @@ export const InfrastructurePage = () => { )} - + {isHostsViewEnabled && } } /> diff --git a/x-pack/plugins/infra/public/pages/metrics/settings/features_configuration_panel.tsx b/x-pack/plugins/infra/public/pages/metrics/settings/features_configuration_panel.tsx new file mode 100644 index 00000000000000..19d7392fb7ca11 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/settings/features_configuration_panel.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiTitle } from '@elastic/eui'; +import { EuiSpacer } from '@elastic/eui'; +import { EuiForm } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { enableInfrastructureHostsView } from '@kbn/observability-plugin/common'; +import { useEditableSettings } from '@kbn/observability-shared-plugin/public'; +import { LazyField } from '@kbn/advanced-settings-plugin/public'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; + +type Props = Pick< + ReturnType, + 'handleFieldChange' | 'settingsEditableConfig' | 'unsavedChanges' +> & { + readOnly: boolean; +}; + +export function FeaturesConfigurationPanel({ + readOnly, + handleFieldChange, + settingsEditableConfig, + unsavedChanges, +}: Props) { + const { + services: { docLinks, notifications }, + } = useKibanaContextForPlugin(); + + return ( + + +

+ +

+
+ + +
+ ); +} diff --git a/x-pack/plugins/infra/public/pages/metrics/settings/source_configuration_settings.tsx b/x-pack/plugins/infra/public/pages/metrics/settings/source_configuration_settings.tsx index 55287a71d3112b..5769f861234c46 100644 --- a/x-pack/plugins/infra/public/pages/metrics/settings/source_configuration_settings.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/settings/source_configuration_settings.tsx @@ -16,7 +16,8 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useCallback } from 'react'; -import { Prompt } from '@kbn/observability-shared-plugin/public'; +import { Prompt, useEditableSettings } from '@kbn/observability-shared-plugin/public'; +import { enableInfrastructureHostsView } from '@kbn/observability-plugin/common'; import { SourceLoadingPage } from '../../../components/source_loading_page'; import { useSourceContext } from '../../../containers/metrics_source'; import { useInfraMLCapabilitiesContext } from '../../../containers/ml/infra_ml_capabilities'; @@ -28,6 +29,7 @@ import { useMetricsBreadcrumbs } from '../../../hooks/use_metrics_breadcrumbs'; import { settingsTitle } from '../../../translations'; import { MetricsPageTemplate } from '../page_template'; +import { FeaturesConfigurationPanel } from './features_configuration_panel'; interface SourceConfigurationSettingsProps { shouldAllowEdit: boolean; } @@ -59,22 +61,33 @@ export const SourceConfigurationSettings = ({ formState, formStateChanges, } = useSourceConfigurationFormState(source && source.configuration); + const infraUiSettings = useEditableSettings('infra_metrics', [enableInfrastructureHostsView]); + + const resetAllUnsavedChanges = useCallback(() => { + resetForm(); + infraUiSettings.cleanUnsavedChanges(); + }, [infraUiSettings, resetForm]); + const persistUpdates = useCallback(async () => { - if (sourceExists) { - await updateSourceConfiguration(formStateChanges); - } else { - await createSourceConfiguration(formState); - } + await Promise.all([ + sourceExists + ? updateSourceConfiguration(formStateChanges) + : createSourceConfiguration(formState), + infraUiSettings.saveAll(), + ]); resetForm(); }, [ sourceExists, + resetForm, updateSourceConfiguration, + formStateChanges, + infraUiSettings, createSourceConfiguration, - resetForm, formState, - formStateChanges, ]); + const hasUnsavedChanges = isFormDirty || Object.keys(infraUiSettings.unsavedChanges).length > 0; + const isWriteable = shouldAllowEdit && (!Boolean(source) || source?.origin !== 'internal'); const { metricIndicesExist, remoteClustersExist } = source?.status ?? {}; @@ -132,6 +145,10 @@ export const SourceConfigurationSettings = ({ )} + + + + {errors.length > 0 ? ( <> @@ -148,7 +165,7 @@ export const SourceConfigurationSettings = ({ {isWriteable && ( - {isLoading ? ( + {isLoading || infraUiSettings.isSaving ? ( - Loading + {i18n.translate('xpack.infra.sourceConfiguration.loadingButtonLabel', { + defaultMessage: 'Loading', + })} @@ -169,10 +188,8 @@ export const SourceConfigurationSettings = ({ data-test-subj="discardSettingsButton" color="danger" iconType="cross" - isDisabled={isLoading || !isFormDirty} - onClick={() => { - resetForm(); - }} + isDisabled={!hasUnsavedChanges} + onClick={resetAllUnsavedChanges} > diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index 1d084845465063..c501108cd0bf61 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -106,7 +106,7 @@ export class Plugin implements InfraClientPluginClass { const startDep$AndHostViewFlag$ = combineLatest([ from(core.getStartServices()), - core.uiSettings.get$(enableInfrastructureHostsView), + core.settings.client.get$(enableInfrastructureHostsView), ]); /** !! Need to be kept in sync with the deepLinks in x-pack/plugins/infra/public/plugin.ts */ @@ -119,46 +119,58 @@ export class Plugin implements InfraClientPluginClass { application: { capabilities }, }, ], - ]) => [ - ...(capabilities.logs.show - ? [ - { - label: 'Logs', - sortKey: 200, - entries: [ - { - label: 'Explorer', - app: 'observability-log-explorer', - path: '/', - isBetaFeature: true, - }, - ...(this.config.featureFlags.logsUIEnabled - ? [ - { label: 'Stream', app: 'logs', path: '/stream' }, - { label: 'Anomalies', app: 'logs', path: '/anomalies' }, - { label: 'Categories', app: 'logs', path: '/log-categories' }, - ] - : []), - ], - }, - ] - : []), - ...(capabilities.infrastructure.show - ? [ - { - label: 'Infrastructure', - sortKey: 300, - entries: [ - { label: 'Inventory', app: 'metrics', path: '/inventory' }, - ...(this.config.featureFlags.metricsExplorerEnabled - ? [{ label: 'Metrics Explorer', app: 'metrics', path: '/explorer' }] - : []), - { label: 'Hosts', isBetaFeature: true, app: 'metrics', path: '/hosts' }, - ], - }, - ] - : []), - ] + isInfrastructureHostsViewEnabled, + ]) => { + return [ + ...(capabilities.logs.show + ? [ + { + label: 'Logs', + sortKey: 200, + entries: [ + { + label: 'Explorer', + app: 'observability-log-explorer', + path: '/', + isBetaFeature: true, + }, + ...(this.config.featureFlags.logsUIEnabled + ? [ + { label: 'Stream', app: 'logs', path: '/stream' }, + { label: 'Anomalies', app: 'logs', path: '/anomalies' }, + { label: 'Categories', app: 'logs', path: '/log-categories' }, + ] + : []), + ], + }, + ] + : []), + ...(capabilities.infrastructure.show + ? [ + { + label: 'Infrastructure', + sortKey: 300, + entries: [ + { label: 'Inventory', app: 'metrics', path: '/inventory' }, + ...(this.config.featureFlags.metricsExplorerEnabled + ? [{ label: 'Metrics Explorer', app: 'metrics', path: '/explorer' }] + : []), + ...(isInfrastructureHostsViewEnabled + ? [ + { + label: 'Hosts', + isBetaFeature: true, + app: 'metrics', + path: '/hosts', + }, + ] + : []), + ], + }, + ] + : []), + ]; + } ) ) ); @@ -230,7 +242,13 @@ export class Plugin implements InfraClientPluginClass { } // !! Need to be kept in sync with the routes in x-pack/plugins/infra/public/pages/metrics/index.tsx - const infraDeepLinks: AppDeepLink[] = [ + const getInfraDeepLinks = ({ + hostsEnabled, + metricsExplorerEnabled, + }: { + hostsEnabled: boolean; + metricsExplorerEnabled: boolean; + }): AppDeepLink[] => [ { id: 'inventory', title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', { @@ -239,15 +257,19 @@ export class Plugin implements InfraClientPluginClass { path: '/inventory', navLinkStatus: AppNavLinkStatus.visible, }, - { - id: 'hosts', - title: i18n.translate('xpack.infra.homePage.metricsHostsTabTitle', { - defaultMessage: 'Hosts', - }), - path: '/hosts', - navLinkStatus: AppNavLinkStatus.visible, - }, - ...(this.config.featureFlags.metricsExplorerEnabled + ...(hostsEnabled + ? [ + { + id: 'hosts', + title: i18n.translate('xpack.infra.homePage.metricsHostsTabTitle', { + defaultMessage: 'Hosts', + }), + path: '/hosts', + navLinkStatus: AppNavLinkStatus.visible, + }, + ] + : []), + ...(metricsExplorerEnabled ? [ { id: 'metrics-explorer', @@ -277,7 +299,10 @@ export class Plugin implements InfraClientPluginClass { appRoute: '/app/metrics', category: DEFAULT_APP_CATEGORIES.observability, updater$: this.appUpdater$, - deepLinks: infraDeepLinks, + deepLinks: getInfraDeepLinks({ + hostsEnabled: core.settings.client.get(enableInfrastructureHostsView), + metricsExplorerEnabled: this.config.featureFlags.metricsExplorerEnabled, + }), mount: async (params: AppMountParameters) => { // mount callback should not use setup dependencies, get start dependencies instead const [coreStart, plugins, pluginStart] = await core.getStartServices(); @@ -308,9 +333,15 @@ export class Plugin implements InfraClientPluginClass { }); startDep$AndHostViewFlag$.subscribe( - ([_startServices]: [[CoreStart, InfraClientStartDeps, InfraClientStartExports], boolean]) => { + ([_startServices, isInfrastructureHostsViewEnabled]: [ + [CoreStart, InfraClientStartDeps, InfraClientStartExports], + boolean + ]) => { this.appUpdater$.next(() => ({ - deepLinks: infraDeepLinks, + deepLinks: getInfraDeepLinks({ + hostsEnabled: isInfrastructureHostsViewEnabled, + metricsExplorerEnabled: this.config.featureFlags.metricsExplorerEnabled, + }), })); } ); diff --git a/x-pack/plugins/infra/tsconfig.json b/x-pack/plugins/infra/tsconfig.json index 2166ae9c7b4c69..0fa2c7c9f69644 100644 --- a/x-pack/plugins/infra/tsconfig.json +++ b/x-pack/plugins/infra/tsconfig.json @@ -71,7 +71,8 @@ "@kbn/aiops-utils", "@kbn/lens-embeddable-utils", "@kbn/metrics-data-access-plugin", - "@kbn/expressions-plugin" + "@kbn/expressions-plugin", + "@kbn/advanced-settings-plugin" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/observability_shared/public/hooks/use_editable_settings.tsx b/x-pack/plugins/observability_shared/public/hooks/use_editable_settings.tsx index 460bb50f57bc70..6be1d28554b48c 100644 --- a/x-pack/plugins/observability_shared/public/hooks/use_editable_settings.tsx +++ b/x-pack/plugins/observability_shared/public/hooks/use_editable_settings.tsx @@ -42,19 +42,20 @@ function getEditableConfig({ } export function useEditableSettings(app: ObservabilityApp, settingsKeys: string[]) { - const { services } = useKibana(); + const { + services: { settings }, + } = useKibana(); - const { uiSettings } = services; const [isSaving, setIsSaving] = useState(false); const [forceReloadSettings, setForceReloadSettings] = useState(0); const [unsavedChanges, setUnsavedChanges] = useState>({}); const settingsEditableConfig = useMemo( () => { - return getEditableConfig({ settingsKeys, uiSettings }); + return getEditableConfig({ settingsKeys, uiSettings: settings?.client }); }, // eslint-disable-next-line react-hooks/exhaustive-deps - [uiSettings, settingsKeys, forceReloadSettings] + [settings, settingsKeys, forceReloadSettings] ); function handleFieldChange(key: string, fieldState: FieldState) { @@ -77,11 +78,11 @@ export function useEditableSettings(app: ObservabilityApp, settingsKeys: string[ } async function saveAll() { - if (uiSettings && !isEmpty(unsavedChanges)) { + if (settings && !isEmpty(unsavedChanges)) { try { setIsSaving(true); const arr = Object.entries(unsavedChanges).map(([key, fieldState]) => - uiSettings.set(key, fieldState.value) + settings.client.set(key, fieldState.value) ); await Promise.all(arr); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index f591e4e4cd68ac..6ed84d45aff898 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -18439,7 +18439,6 @@ "xpack.infra.deprecations.timestampAdjustIndexing": "Ajustez votre indexation pour utiliser \"{field}\" comme horodatage.", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "Dernières {duration} de données pour l'heure sélectionnée", "xpack.infra.hostsViewPage.errorOnCreateOrLoadDataview": "Une erreur s’est produite lors de la création d’une vue de données : {metricAlias}. Essayez de recharger la page.", - "xpack.infra.hostsViewPage.landing.calloutRoleClarificationWithDocsLink": "Un rôle avec accès aux paramètres avancés dans Kibana sera nécessaire. {docsLink}", "xpack.infra.hostsViewPage.kpi.subtitle.average.limit": "Moyenne (de {limit} hôtes)", "xpack.infra.hostsViewPage.kpi.subtitle.hostCount.limit": "Limité à {limit}", "xpack.infra.hostsViewPage.table.selectedHostsButton": "Sélection effectuée de {selectedHostsCount} {selectedHostsCount, plural, =1 {hôte} one {hôtes} many {hôtes} other {hôtes}}", @@ -18667,12 +18666,6 @@ "xpack.infra.hostsViewPage.hostLimit": "Limite de l'hôte", "xpack.infra.hostsViewPage.hostLimit.tooltip": "Pour garantir des performances de recherche plus rapides, le nombre d'hôtes retournés est limité.", "xpack.infra.hostsViewPage.kpi.hostCount.title": "Hôtes", - "xpack.infra.hostsViewPage.landing.calloutReachOutToYourKibanaAdministrator": "Votre rôle d'utilisateur ne dispose pas des privilèges suffisants pour activer cette fonctionnalité - veuillez \n contacter votre administrateur Kibana et lui demander de visiter cette page pour activer la fonctionnalité.", - "xpack.infra.hostsViewPage.landing.enableHostsView": "Activer la vue des hôtes", - "xpack.infra.hostsViewPage.landing.introMessage": "Bienvenue sur la fonctionnalité \"Hôtes\", désormais disponible en version bêta. Avec ce puissant outil, \n vous pouvez facilement voir et analyser vos hôtes et identifier tout problème afin de les corriger rapidement. \n Obtenez une vue détaillée des indicateurs pour vos hôtes afin de savoir lesquels déclenchent le plus d’alertes, et filtrez \n les hôtes que vous voulez analyser à l'aide de tout filtre KQL ainsi que de répartitions simples comme le fournisseur cloud et \n le système d'exploitation.", - "xpack.infra.hostsViewPage.landing.introTitle": "Analyse de l'hôte", - "xpack.infra.hostsViewPage.landing.learnMore": "En savoir plus", - "xpack.infra.hostsViewPage.landing.tryTheFeatureMessage": "Ceci est une version bêta de la fonctionnalité, donc nous apprécierions recevoir vos \n commentaires tandis que nous continuons à la développer et à l'améliorer. Pour accéder à la fonctionnalité, \n activez-la simplement ci-dessous (ou contactez votre administrateur interne si indisponible). \n Ne passez pas à côté de cette puissante fonctionnalité : essayez-là dès aujourd'hui !", "xpack.infra.hostsViewPage.metrics.tooltip.cpuUsage": "Pourcentage de temps CPU utilisé dans les états autres que Inactif et IOWait, normalisée par le nombre de cœurs de processeur. Cela inclut le temps passé à la fois sur l'espace utilisateur et sur l'espace du noyau.", "xpack.infra.hostsViewPage.metrics.tooltip.diskLatency": "Temps passé à gérer les requêtes de disque.", "xpack.infra.hostsViewPage.metrics.tooltip.diskSpaceUsage": "Pourcentage d’espace disque utilisé.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b9951916425215..15d66275a00ba5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -18453,7 +18453,6 @@ "xpack.infra.deprecations.timestampAdjustIndexing": "インデックスを調整し、\"{field}\"をタイムスタンプとして使用します。", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "指定期間のデータの最後の{duration}", "xpack.infra.hostsViewPage.errorOnCreateOrLoadDataview": "データビューの作成中にエラーが発生しました:{metricAlias}。ページを再読み込みしてください。", - "xpack.infra.hostsViewPage.landing.calloutRoleClarificationWithDocsLink": "Kibanaの高度な設定にアクセスできるロールが必要です。{docsLink}", "xpack.infra.hostsViewPage.kpi.subtitle.average.limit": "({limit}ホストの)平均", "xpack.infra.hostsViewPage.kpi.subtitle.hostCount.limit": "{limit}に制限", "xpack.infra.hostsViewPage.table.selectedHostsButton": "{selectedHostsCount}件の{selectedHostsCount, plural, =1 {ホスト} other {ホスト}}が選択済み", @@ -18681,12 +18680,6 @@ "xpack.infra.hostsViewPage.hostLimit": "ホスト制限", "xpack.infra.hostsViewPage.hostLimit.tooltip": "クエリパフォーマンスを確実に高めるために、返されるホスト数には制限があります", "xpack.infra.hostsViewPage.kpi.hostCount.title": "ホスト", - "xpack.infra.hostsViewPage.landing.calloutReachOutToYourKibanaAdministrator": "ユーザーロールには、この機能を有効にするための十分な権限がありません。 \n この機能を有効にするために、Kibana管理者に連絡して、このページにアクセスするように依頼してください。", - "xpack.infra.hostsViewPage.landing.enableHostsView": "ホストビューを有効化", - "xpack.infra.hostsViewPage.landing.introMessage": "「ホスト」機能へようこそ!ベータ版でご利用いただけるようになりました。この強力なツールを使用すると、\n ホストを簡単に表示、分析し、あらゆる問題を特定して、迅速に対処できます。\n ホストのメトリックを詳細に表示し、どのメトリックが最も多くのアラートをトリガーしているかを確認し、 \n 任意のKQLフィルターを使用して分析したいホストや、クラウドプロバイダーやオペレーティングシステムといった簡単な内訳をフィルターできます \n 。", - "xpack.infra.hostsViewPage.landing.introTitle": "ホスト分析", - "xpack.infra.hostsViewPage.landing.learnMore": "詳細", - "xpack.infra.hostsViewPage.landing.tryTheFeatureMessage": "この機能はベータ版です。ご意見をお聞かせください。 \n 機能の開発と改善に役立てます。この機能を使用するには、\n 以下で有効化します(あるいは、使用できない場合は、社内管理者に問い合わせてください)。\n この強力な機能をぜひご利用ください。今すぐお試しください。", "xpack.infra.hostsViewPage.metrics.tooltip.cpuUsage": "アイドルおよびIOWait以外の状態で費やされたCPU時間の割合を、CPUコア数で正規化したもの。これにはユーザースペースとカーネルスペースの両方で費やされた時間が含まれます。", "xpack.infra.hostsViewPage.metrics.tooltip.diskLatency": "ディスクリクエストの処理に費やされた時間。", "xpack.infra.hostsViewPage.metrics.tooltip.diskSpaceUsage": "使用済みディスク容量の割合。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index fbef44d66792ed..b3ee160e83978f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -18453,7 +18453,6 @@ "xpack.infra.deprecations.timestampAdjustIndexing": "调整索引以将“{field}”用作时间戳。", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "选定时间过去 {duration}的数据", "xpack.infra.hostsViewPage.errorOnCreateOrLoadDataview": "尝试创建以下数据视图时出错:{metricAlias}。尝试重新加载该页面。", - "xpack.infra.hostsViewPage.landing.calloutRoleClarificationWithDocsLink": "他们将需要有权访问 Kibana 中的高级设置的角色。{docsLink}", "xpack.infra.hostsViewPage.kpi.subtitle.average.limit": "平均值(属于 {limit} 台主机)", "xpack.infra.hostsViewPage.kpi.subtitle.hostCount.limit": "限定为 {limit}", "xpack.infra.hostsViewPage.table.selectedHostsButton": "已选定 {selectedHostsCount} 个{selectedHostsCount, plural, =1 {主机} other {主机}}", @@ -18681,12 +18680,6 @@ "xpack.infra.hostsViewPage.hostLimit": "主机限制", "xpack.infra.hostsViewPage.hostLimit.tooltip": "为确保更快的查询性能,对返回的主机数量实施了限制", "xpack.infra.hostsViewPage.kpi.hostCount.title": "主机", - "xpack.infra.hostsViewPage.landing.calloutReachOutToYourKibanaAdministrator": "您的用户角色权限不足,无法启用此功能 - 请 \n 联系您的 Kibana 管理员,要求他们访问此页面以启用该功能。", - "xpack.infra.hostsViewPage.landing.enableHostsView": "启用主机视图", - "xpack.infra.hostsViewPage.landing.introMessage": "欢迎使用“主机”功能,该功能现在为公测版!使用这个强大的工具,\n 您可以轻松查看并分析主机,并确定任何问题以便快速予以解决。\n 获取您主机的详细指标视图,了解哪些指标触发了大多数告警, \n 并使用任何 KQL 筛选以及云提供商和操作系统等常见细目筛选 \n 您要分析的主机。", - "xpack.infra.hostsViewPage.landing.introTitle": "主机分析", - "xpack.infra.hostsViewPage.landing.learnMore": "了解详情", - "xpack.infra.hostsViewPage.landing.tryTheFeatureMessage": "这是公测版功能,我们乐于收到您的反馈, \n 以便我们继续开发和改进该功能。要访问该功能,\n 只需在下面直接启用即可(或在不可用时联系您的内部管理员)。\n 不要错过这个强大的功能 - 立即试用!", "xpack.infra.hostsViewPage.metrics.tooltip.cpuUsage": "CPU 在空闲和 IOWait 状态以外所花费时间的百分比,按 CPU 核心数进行标准化。这包括在用户空间和内核空间上花费的时间。", "xpack.infra.hostsViewPage.metrics.tooltip.diskLatency": "处理磁盘请求所花费的时间。", "xpack.infra.hostsViewPage.metrics.tooltip.diskSpaceUsage": "已用磁盘空间百分比。", diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/test/functional/apps/infra/hosts_view.ts index e8f7730522f428..fa9008bf5cc246 100644 --- a/x-pack/test/functional/apps/infra/hosts_view.ts +++ b/x-pack/test/functional/apps/infra/hosts_view.ts @@ -94,7 +94,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const kibanaServer = getService('kibanaServer'); const observability = getService('observability'); const retry = getService('retry'); - const security = getService('security'); const testSubjects = getService('testSubjects'); const pageObjects = getPageObjects([ 'assetDetails', @@ -111,47 +110,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const setHostViewEnabled = (value: boolean = true) => kibanaServer.uiSettings.update({ [enableInfrastructureHostsView]: value }); - const loginWithReadOnlyUser = async () => { - const roleCreation = await security.role.create('global_hosts_read_privileges_role', { - elasticsearch: { - indices: [{ names: ['metricbeat-*'], privileges: ['read', 'view_index_metadata'] }], - }, - kibana: [ - { - feature: { - infrastructure: ['read'], - advancedSettings: ['read'], - }, - spaces: ['*'], - }, - ], - }); - - const userCreation = security.user.create('global_hosts_read_privileges_user', { - password: 'global_hosts_read_privileges_user-password', - roles: ['global_hosts_read_privileges_role'], - full_name: 'test user', - }); - - await Promise.all([roleCreation, userCreation]); - - await pageObjects.security.forceLogout(); - await pageObjects.security.login( - 'global_hosts_read_privileges_user', - 'global_hosts_read_privileges_user-password', - { - expectSpaceSelector: false, - } - ); - }; - - const logoutAndDeleteReadOnlyUser = () => - Promise.all([ - pageObjects.security.forceLogout(), - security.role.delete('global_hosts_read_privileges_role'), - security.user.delete('global_hosts_read_privileges_user'), - ]); - const returnTo = async (path: string, timeout = 2000) => retry.waitForWithTimeout('returned to hosts view', timeout, async () => { await browser.goBack(); @@ -200,65 +158,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(pageUrl).to.contain(HOSTS_VIEW_PATH); }); - describe('#Landing page', () => { - beforeEach(async () => { - await setHostViewEnabled(false); - }); - - afterEach(async () => { - await setHostViewEnabled(true); - }); - - describe('User with read permission', () => { - beforeEach(async () => { - await loginWithReadOnlyUser(); - await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); - await pageObjects.header.waitUntilLoadingHasFinished(); - }); - - afterEach(async () => { - await logoutAndDeleteReadOnlyUser(); - }); - - it('Should show hosts landing page with callout when the hosts view is disabled', async () => { - await pageObjects.infraHostsView.getBetaBadgeExists(); - const landingPageDisabled = - await pageObjects.infraHostsView.getHostsLandingPageDisabled(); - const learnMoreDocsUrl = await pageObjects.infraHostsView.getHostsLandingPageDocsLink(); - const parsedUrl = new URL(learnMoreDocsUrl); - - expect(parsedUrl.host).to.be('www.elastic.co'); - expect(parsedUrl.pathname).to.be('/guide/en/kibana/current/kibana-privileges.html'); - expect(landingPageDisabled).to.contain( - 'Your user role doesn’t have sufficient privileges to enable this feature' - ); - }); - }); - - describe('Admin user', () => { - beforeEach(async () => { - await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); - await pageObjects.header.waitUntilLoadingHasFinished(); - }); - - it('as an admin, should see an enable button when the hosts view is disabled', async () => { - const landingPageEnableButton = - await pageObjects.infraHostsView.getHostsLandingPageEnableButton(); - const landingPageEnableButtonText = await landingPageEnableButton.getVisibleText(); - expect(landingPageEnableButtonText).to.eql('Enable hosts view'); - }); - - it('as an admin, should be able to enable the hosts view feature', async () => { - await pageObjects.infraHostsView.clickEnableHostViewButton(); - - const titleElement = await find.byCssSelector('h1'); - const title = await titleElement.getVisibleText(); - - expect(title).to.contain('Hosts'); - }); - }); - }); - describe('#Single Host Flyout', () => { before(async () => { await setHostViewEnabled(true); diff --git a/x-pack/test/functional/page_objects/infra_hosts_view.ts b/x-pack/test/functional/page_objects/infra_hosts_view.ts index 83628e1eae02a3..3d37fc4da913fc 100644 --- a/x-pack/test/functional/page_objects/infra_hosts_view.ts +++ b/x-pack/test/functional/page_objects/infra_hosts_view.ts @@ -46,28 +46,6 @@ export function InfraHostsViewProvider({ getService }: FtrProviderContext) { return await testSubjects.click('inventory-hostsView-link-badge'); }, - // Splash screen - - async getHostsLandingPageDisabled() { - const container = await testSubjects.find('hostView-no-enable-access'); - const containerText = await container.getVisibleText(); - return containerText; - }, - - async getHostsLandingPageDocsLink() { - const container = await testSubjects.find('hostsView-docs-link'); - const containerText = await container.getAttribute('href'); - return containerText; - }, - - async getHostsLandingPageEnableButton() { - return testSubjects.find('hostsView-enable-feature-button'); - }, - - async clickEnableHostViewButton() { - return testSubjects.click('hostsView-enable-feature-button'); - }, - // Table async getHostsTable() {