From 59924243127bb314acb5d921bff882079ce926e2 Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Mon, 6 Jul 2020 18:52:00 -0400 Subject: [PATCH] add button link to ingest (#70142) update security solution empty page --- .../sections/epm/screens/home/index.tsx | 15 ++++- .../detection_engine/detection_engine.tsx | 4 +- .../detection_engine_empty_page.test.tsx | 19 ------ .../detection_engine_empty_page.tsx | 28 -------- .../detection_engine/rules/details/index.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../common/components/empty_page/index.tsx | 15 +++-- .../common/hooks/endpoint/ingest_enabled.ts | 34 ++++++++++ .../public/common/translations.ts | 14 ++-- .../public/hosts/pages/details/index.tsx | 4 +- .../public/hosts/pages/hosts.tsx | 4 +- .../public/hosts/pages/hosts_empty_page.tsx | 34 ---------- .../pages/endpoint_hosts/view/hooks.ts | 6 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../public/network/pages/ip_details/index.tsx | 4 +- .../public/network/pages/network.tsx | 4 +- .../network/pages/network_empty_page.tsx | 34 ---------- .../components/overview_empty/index.tsx | 54 +++++++++++++-- .../public/overview/pages/overview.test.tsx | 66 ++++++++++++++----- .../source_status/elasticsearch_adapter.ts | 3 + 20 files changed, 180 insertions(+), 170 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx create mode 100644 x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts delete mode 100644 x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.tsx delete mode 100644 x-pack/plugins/security_solution/public/network/pages/network_empty_page.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx index e00b63e29019e1..c68833c1b2d951 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx @@ -5,7 +5,7 @@ */ import React, { useState } from 'react'; -import { useRouteMatch, Switch, Route } from 'react-router-dom'; +import { useRouteMatch, Switch, Route, useLocation, useHistory } from 'react-router-dom'; import { Props as EuiTabProps } from '@elastic/eui/src/components/tabs/tab'; import { i18n } from '@kbn/i18n'; import { PAGE_ROUTING_PATHS } from '../../../../constants'; @@ -114,7 +114,10 @@ function InstalledPackages() { function AvailablePackages() { useBreadcrumbs('integrations_all'); - const [selectedCategory, setSelectedCategory] = useState(''); + const history = useHistory(); + const queryParams = new URLSearchParams(useLocation().search); + const initialCategory = queryParams.get('category') || ''; + const [selectedCategory, setSelectedCategory] = useState(initialCategory); const { data: categoryPackagesRes, isLoading: isLoadingPackages } = useGetPackages({ category: selectedCategory, }); @@ -141,7 +144,13 @@ function AvailablePackages() { isLoading={isLoadingCategories} categories={categories} selectedCategory={selectedCategory} - onCategoryChange={({ id }: CategorySummaryItem) => setSelectedCategory(id)} + onCategoryChange={({ id }: CategorySummaryItem) => { + // clear category query param in the url + if (queryParams.get('category')) { + history.push({}); + } + setSelectedCategory(id); + }} /> ) : null; diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx index 5c525a85534775..b39d51e2de95fb 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx @@ -31,7 +31,7 @@ import { NoWriteAlertsCallOut } from '../../components/no_write_alerts_callout'; import { AlertsHistogramPanel } from '../../components/alerts_histogram_panel'; import { alertsHistogramOptions } from '../../components/alerts_histogram_panel/config'; import { useUserInfo } from '../../components/user_info'; -import { DetectionEngineEmptyPage } from './detection_engine_empty_page'; +import { OverviewEmpty } from '../../../overview/components/overview_empty'; import { DetectionEngineNoIndex } from './detection_engine_no_signal_index'; import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; import { DetectionEngineUserUnauthenticated } from './detection_engine_user_unauthenticated'; @@ -159,7 +159,7 @@ export const DetectionEnginePageComponent: React.FC = ({ ) : ( - + )} diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx deleted file mode 100644 index 039c878b121a09..00000000000000 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; - -import { DetectionEngineEmptyPage } from './detection_engine_empty_page'; -jest.mock('../../../common/lib/kibana'); - -describe('DetectionEngineEmptyPage', () => { - it('renders correctly', () => { - const wrapper = shallow(); - - expect(wrapper.find('EmptyPage')).toHaveLength(1); - }); -}); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx deleted file mode 100644 index 0c58f5620964ba..00000000000000 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import { useKibana } from '../../../common/lib/kibana'; -import { EmptyPage } from '../../../common/components/empty_page'; -import * as i18n from '../../../common/translations'; -import { ADD_DATA_PATH } from '../../../../common/constants'; - -export const DetectionEngineEmptyPage = React.memo(() => ( - -)); -DetectionEngineEmptyPage.displayName = 'DetectionEngineEmptyPage'; diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx index b937e95c0a57e4..c73613842a8724 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx @@ -43,7 +43,7 @@ import { DetectionEngineHeaderPage } from '../../../../components/detection_engi import { AlertsHistogramPanel } from '../../../../components/alerts_histogram_panel'; import { AlertsTable } from '../../../../components/alerts_table'; import { useUserInfo } from '../../../../components/user_info'; -import { DetectionEngineEmptyPage } from '../../detection_engine_empty_page'; +import { OverviewEmpty } from '../../../../../overview/components/overview_empty'; import { useAlertInfo } from '../../../../components/alerts_info'; import { StepDefineRule } from '../../../../components/rules/step_define_rule'; import { StepScheduleRule } from '../../../../components/rules/step_schedule_rule'; @@ -426,7 +426,7 @@ export const RuleDetailsPageComponent: FC = ({ - + )} diff --git a/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap index 65893f84f5e563..623b15aa76d127 100644 --- a/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap @@ -18,7 +18,7 @@ exports[`renders correctly 1`] = ` } - iconType="securityAnalyticsApp" + iconType="logoSecurity" title={

My Super Title diff --git a/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx b/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx index a067c1d28f87fa..f6d6752729b6d9 100644 --- a/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx @@ -5,7 +5,7 @@ */ import { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, IconType } from '@elastic/eui'; -import React from 'react'; +import React, { MouseEventHandler, ReactNode } from 'react'; import styled from 'styled-components'; const EmptyPrompt = styled(EuiEmptyPrompt)` @@ -19,12 +19,14 @@ interface EmptyPageProps { actionPrimaryLabel: string; actionPrimaryTarget?: string; actionPrimaryUrl: string; + actionPrimaryFill?: boolean; actionSecondaryIcon?: IconType; actionSecondaryLabel?: string; actionSecondaryTarget?: string; actionSecondaryUrl?: string; + actionSecondaryOnClick?: MouseEventHandler; 'data-test-subj'?: string; - message?: string; + message?: ReactNode; title: string; } @@ -34,23 +36,25 @@ export const EmptyPage = React.memo( actionPrimaryLabel, actionPrimaryTarget, actionPrimaryUrl, + actionPrimaryFill = true, actionSecondaryIcon, actionSecondaryLabel, actionSecondaryTarget, actionSecondaryUrl, + actionSecondaryOnClick, message, title, ...rest }) => ( {title}

} body={message &&

{message}

} actions={ ( {actionSecondaryLabel && actionSecondaryUrl && ( + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} {actionSecondaryLabel} diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts new file mode 100644 index 00000000000000..c201d85a270c02 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; + +/** + * Returns an object which ingest permissions are allowed + */ +export const useIngestEnabledCheck = (): { + allEnabled: boolean; + show: boolean; + write: boolean; + read: boolean; +} => { + const { services } = useKibana(); + + // Check if Ingest Manager is present in the configuration + const show = services.application.capabilities.ingestManager?.show ?? false; + const write = services.application.capabilities.ingestManager?.write ?? false; + const read = services.application.capabilities.ingestManager?.read ?? false; + + // Check if all Ingest Manager permissions are enabled + const allEnabled = show && read && write ? true : false; + + return { + allEnabled, + show, + write, + read, + }; +}; diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 677543ec0dba68..413119fb40f141 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -10,11 +10,6 @@ export const EMPTY_TITLE = i18n.translate('xpack.securitySolution.pages.common.e defaultMessage: 'Welcome to Security Solution. Let’s get you started.', }); -export const EMPTY_MESSAGE = i18n.translate('xpack.securitySolution.pages.common.emptyMessage', { - defaultMessage: - 'To begin using security information and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. Let’s do that now!', -}); - export const EMPTY_ACTION_PRIMARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionPrimary', { @@ -25,6 +20,13 @@ export const EMPTY_ACTION_PRIMARY = i18n.translate( export const EMPTY_ACTION_SECONDARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionSecondary', { - defaultMessage: 'View getting started guide', + defaultMessage: 'getting started guide.', + } +); + +export const EMPTY_ACTION_ENDPOINT = i18n.translate( + 'xpack.securitySolution.pages.common.emptyActionEndpoint', + { + defaultMessage: 'Add data with Elastic Agent (Beta)', } ); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx index 46823f037b61cf..bb0317f0482b03 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx @@ -38,7 +38,7 @@ import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '. import { SpyRoute } from '../../../common/utils/route/spy_routes'; import { esQuery, Filter } from '../../../../../../../src/plugins/data/public'; -import { HostsEmptyPage } from '../hosts_empty_page'; +import { OverviewEmpty } from '../../../overview/components/overview_empty'; import { HostDetailsTabs } from './details_tabs'; import { navTabsHostDetails } from './nav_tabs'; import { HostDetailsProps } from './types'; @@ -194,7 +194,7 @@ const HostDetailsComponent = React.memo( - + )} diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx index 90438aec7c27e4..a2f83bf0965f36 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx @@ -33,7 +33,7 @@ import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from import { SpyRoute } from '../../common/utils/route/spy_routes'; import { esQuery } from '../../../../../../src/plugins/data/public'; import { useMlCapabilities } from '../../common/components/ml_popover/hooks/use_ml_capabilities'; -import { HostsEmptyPage } from './hosts_empty_page'; +import { OverviewEmpty } from '../../overview/components/overview_empty'; import { HostsTabs } from './hosts_tabs'; import { navTabsHosts } from './nav_tabs'; import * as i18n from './translations'; @@ -141,7 +141,7 @@ export const HostsComponent = React.memo( - + )} diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.tsx deleted file mode 100644 index a01e249561e5c5..00000000000000 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import { EmptyPage } from '../../common/components/empty_page'; -import { useKibana } from '../../common/lib/kibana'; -import * as i18n from '../../common/translations'; -import { ADD_DATA_PATH } from '../../../common/constants'; - -export const HostsEmptyPage = React.memo(() => { - const { http, docLinks } = useKibana().services; - const basePath = http.basePath.get(); - - return ( - - ); -}); - -HostsEmptyPage.displayName = 'HostsEmptyPage'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts index 68198b691da403..b048a8f69b5d23 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts @@ -24,16 +24,16 @@ export function useHostSelector(selector: (state: HostState) => TSele /** * Returns an object that contains Ingest app and URL information */ -export const useHostIngestUrl = (): { url: string; appId: string; appPath: string } => { +export const useIngestUrl = (subpath: string): { url: string; appId: string; appPath: string } => { const { services } = useKibana(); return useMemo(() => { - const appPath = `#/fleet`; + const appPath = `#/${subpath}`; return { url: `${services.application.getUrlForApp('ingestManager')}${appPath}`, appId: 'ingestManager', appPath, }; - }, [services.application]); + }, [services.application, subpath]); }; /** diff --git a/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap index d7af8d6910f45c..93dafeff34ce9f 100644 --- a/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap @@ -9,7 +9,7 @@ exports[`Ip Details it matches the snapshot 1`] = ` border={true} title="123.456.78.90" /> - + - + )} diff --git a/x-pack/plugins/security_solution/public/network/pages/network.tsx b/x-pack/plugins/security_solution/public/network/pages/network.tsx index bdaac1ac049e5e..5767951f9f6b31 100644 --- a/x-pack/plugins/security_solution/public/network/pages/network.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/network.tsx @@ -34,7 +34,7 @@ import { SpyRoute } from '../../common/utils/route/spy_routes'; import { networkModel } from '../store'; import { navTabsNetwork, NetworkRoutes, NetworkRoutesLoading } from './navigation'; import { filterNetworkData } from './navigation/alerts_query_tab_body'; -import { NetworkEmptyPage } from './network_empty_page'; +import { OverviewEmpty } from '../../overview/components/overview_empty'; import * as i18n from './translations'; import { NetworkComponentProps } from './types'; import { NetworkRouteType } from './navigation/types'; @@ -164,7 +164,7 @@ const NetworkComponent = React.memo( ) : ( - + )} diff --git a/x-pack/plugins/security_solution/public/network/pages/network_empty_page.tsx b/x-pack/plugins/security_solution/public/network/pages/network_empty_page.tsx deleted file mode 100644 index dce3f85797f121..00000000000000 --- a/x-pack/plugins/security_solution/public/network/pages/network_empty_page.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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import { useKibana } from '../../common/lib/kibana'; -import { EmptyPage } from '../../common/components/empty_page'; -import * as i18n from '../../common/translations'; -import { ADD_DATA_PATH } from '../../../common/constants'; - -export const NetworkEmptyPage = React.memo(() => { - const { http, docLinks } = useKibana().services; - const basePath = http.basePath.get(); - - return ( - - ); -}); - -NetworkEmptyPage.displayName = 'NetworkEmptyPage'; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx index 00db437bce11ed..33413be10079e5 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx @@ -5,27 +5,67 @@ */ import React from 'react'; - +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiLink } from '@elastic/eui'; import * as i18nCommon from '../../../common/translations'; import { EmptyPage } from '../../../common/components/empty_page'; import { useKibana } from '../../../common/lib/kibana'; import { ADD_DATA_PATH } from '../../../../common/constants'; +import { useIngestUrl } from '../../../management/pages/endpoint_hosts/view/hooks'; +import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler'; +import { useIngestEnabledCheck } from '../../../common/hooks/endpoint/ingest_enabled'; const OverviewEmptyComponent: React.FC = () => { const { http, docLinks } = useKibana().services; const basePath = http.basePath.get(); + const { appId: ingestAppId, appPath: ingestPath, url: ingestUrl } = useIngestUrl( + 'integrations?category=security' + ); + const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath }); + const { allEnabled: isIngestEnabled } = useIngestEnabledCheck(); - return ( + return isIngestEnabled === true ? ( + + + + {i18nCommon.EMPTY_ACTION_SECONDARY} + + + } + title={i18nCommon.EMPTY_TITLE} + /> + ) : ( + + + {i18nCommon.EMPTY_ACTION_SECONDARY} + + + } title={i18nCommon.EMPTY_TITLE} /> ); diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx index 9613a1e7210a3b..6f13f64ca1bffa 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx @@ -16,6 +16,7 @@ import { UseMessagesStorage, } from '../../common/containers/local_storage/use_messages_storage'; import { Overview } from './index'; +import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled'; jest.mock('../../common/lib/kibana'); jest.mock('../../common/containers/source'); @@ -33,6 +34,7 @@ jest.mock('../../common/components/search_bar', () => ({ jest.mock('../../common/components/query_bar', () => ({ QueryBar: () => null, })); +jest.mock('../../common/hooks/endpoint/ingest_enabled'); jest.mock('../../common/containers/local_storage/use_messages_storage'); const endpointNoticeMessage = (hasMessageValue: boolean) => { @@ -47,26 +49,54 @@ const endpointNoticeMessage = (hasMessageValue: boolean) => { describe('Overview', () => { describe('rendering', () => { - test('it renders the Setup Instructions text when no index is available', async () => { - (useWithSource as jest.Mock).mockReturnValue({ - indicesExist: false, + describe('when no index is available', () => { + beforeEach(() => { + (useWithSource as jest.Mock).mockReturnValue({ + indicesExist: false, + }); + (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: false }); + const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock< + UseMessagesStorage + >; + mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); }); - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); + it('renders the Setup Instructions text', () => { + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(true); + }); - const wrapper = mount( - - - - - - ); + it('does not show Endpoint get ready button when ingest is not enabled', () => { + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page-secondary-action"]').exists()).toBe(false); + }); - expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(true); + it('shows Endpoint get ready button when ingest is enabled', () => { + (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page-secondary-action"]').exists()).toBe(true); + }); }); - test('it DOES NOT render the Getting started text when an index is available', async () => { + it('it DOES NOT render the Getting started text when an index is available', () => { (useWithSource as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, @@ -85,7 +115,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(false); }); - test('it DOES render the Endpoint banner when the endpoint index is NOT available AND storage is NOT set', async () => { + test('it DOES render the Endpoint banner when the endpoint index is NOT available AND storage is NOT set', () => { (useWithSource as jest.Mock).mockReturnValueOnce({ indicesExist: true, indexPattern: {}, @@ -109,7 +139,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(true); }); - test('it does NOT render the Endpoint banner when the endpoint index is NOT available but storage is set', async () => { + test('it does NOT render the Endpoint banner when the endpoint index is NOT available but storage is set', () => { (useWithSource as jest.Mock).mockReturnValueOnce({ indicesExist: true, indexPattern: {}, @@ -133,7 +163,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(false); }); - test('it does NOT render the Endpoint banner when the endpoint index is available AND storage is set', async () => { + test('it does NOT render the Endpoint banner when the endpoint index is available AND storage is set', () => { (useWithSource as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, @@ -152,7 +182,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(false); }); - test('it does NOT render the Endpoint banner when an index IS available but storage is NOT set', async () => { + test('it does NOT render the Endpoint banner when an index IS available but storage is NOT set', () => { (useWithSource as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, diff --git a/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts index 8872d347da8267..ab491f54854e44 100644 --- a/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts +++ b/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts @@ -8,6 +8,7 @@ import { FrameworkAdapter, FrameworkRequest } from '../framework'; import { SourceStatusAdapter } from './index'; import { buildQuery } from './query.dsl'; import { ApmServiceNameAgg } from './types'; +import { ENDPOINT_METADATA_INDEX } from '../../../common/constants'; const APM_INDEX_NAME = 'apm-*-transaction*'; @@ -18,6 +19,8 @@ export class ElasticsearchSourceStatusAdapter implements SourceStatusAdapter { // Intended flow to determine app-empty state is to first check siem indices (as this is a quick shard count), and // if no shards exist only then perform the heavier APM query. This optimizes for normal use when siem data exists try { + // Add endpoint metadata index to indices to check + indexNames.push(ENDPOINT_METADATA_INDEX); // Remove APM index if exists, and only query if length > 0 in case it's the only index provided const nonApmIndexNames = indexNames.filter((name) => name !== APM_INDEX_NAME); const indexCheckResponse = await (nonApmIndexNames.length > 0