Skip to content

Commit 65a111f

Browse files
authored
Task/host enhancements (#59671)
functional tests and ui updates to endpoint host details
1 parent ac5e323 commit 65a111f

File tree

36 files changed

+623
-545
lines changed

36 files changed

+623
-545
lines changed

x-pack/plugins/endpoint/common/generate_data.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,23 @@ describe('data generator', () => {
2121
const generator1 = new EndpointDocGenerator('seed');
2222
const generator2 = new EndpointDocGenerator('seed');
2323
const timestamp = new Date().getTime();
24-
const metadata1 = generator1.generateEndpointMetadata(timestamp);
25-
const metadata2 = generator2.generateEndpointMetadata(timestamp);
24+
const metadata1 = generator1.generateHostMetadata(timestamp);
25+
const metadata2 = generator2.generateHostMetadata(timestamp);
2626
expect(metadata1).toEqual(metadata2);
2727
});
2828

2929
it('creates different documents with different random seeds', () => {
3030
const generator1 = new EndpointDocGenerator('seed');
3131
const generator2 = new EndpointDocGenerator('different seed');
3232
const timestamp = new Date().getTime();
33-
const metadata1 = generator1.generateEndpointMetadata(timestamp);
34-
const metadata2 = generator2.generateEndpointMetadata(timestamp);
33+
const metadata1 = generator1.generateHostMetadata(timestamp);
34+
const metadata2 = generator2.generateHostMetadata(timestamp);
3535
expect(metadata1).not.toEqual(metadata2);
3636
});
3737

38-
it('creates endpoint metadata documents', () => {
38+
it('creates host metadata documents', () => {
3939
const timestamp = new Date().getTime();
40-
const metadata = generator.generateEndpointMetadata(timestamp);
40+
const metadata = generator.generateHostMetadata(timestamp);
4141
expect(metadata['@timestamp']).toEqual(timestamp);
4242
expect(metadata.event.created).toEqual(timestamp);
4343
expect(metadata.endpoint).not.toBeNull();

x-pack/plugins/endpoint/common/generate_data.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import uuid from 'uuid';
88
import seedrandom from 'seedrandom';
9-
import { AlertEvent, EndpointEvent, EndpointMetadata, OSFields, HostFields } from './types';
9+
import { AlertEvent, EndpointEvent, HostMetadata, OSFields, HostFields } from './types';
1010

1111
export type Event = AlertEvent | EndpointEvent;
1212

@@ -104,8 +104,8 @@ export class EndpointDocGenerator {
104104
this.commonInfo = this.createHostData();
105105
}
106106

107-
// This function will create new values for all the host fields, so documents from a different endpoint can be created
108-
// This provides a convenient way to make documents from multiple endpoints that are all tied to a single seed value
107+
// This function will create new values for all the host fields, so documents from a different host can be created
108+
// This provides a convenient way to make documents from multiple hosts that are all tied to a single seed value
109109
public randomizeHostData() {
110110
this.commonInfo = this.createHostData();
111111
}
@@ -129,7 +129,7 @@ export class EndpointDocGenerator {
129129
};
130130
}
131131

132-
public generateEndpointMetadata(ts = new Date().getTime()): EndpointMetadata {
132+
public generateHostMetadata(ts = new Date().getTime()): HostMetadata {
133133
return {
134134
'@timestamp': ts,
135135
event: {

x-pack/plugins/endpoint/common/types.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ export interface AlertResultList {
8383
prev: string | null;
8484
}
8585

86-
export interface EndpointResultList {
87-
/* the endpoints restricted by the page size */
88-
endpoints: EndpointMetadata[];
89-
/* the total number of unique endpoints in the index */
86+
export interface HostResultList {
87+
/* the hosts restricted by the page size */
88+
hosts: HostMetadata[];
89+
/* the total number of unique hosts in the index */
9090
total: number;
9191
/* the page size requested */
9292
request_page_size: number;
@@ -243,7 +243,7 @@ interface AlertMetadata {
243243
*/
244244
export type AlertData = AlertEvent & AlertMetadata;
245245

246-
export interface EndpointMetadata {
246+
export type HostMetadata = Immutable<{
247247
'@timestamp': number;
248248
event: {
249249
created: number;
@@ -258,7 +258,7 @@ export interface EndpointMetadata {
258258
version: string;
259259
};
260260
host: HostFields;
261-
}
261+
}>;
262262

263263
/**
264264
* Represents `total` response from Elasticsearch after ES 7.0.

x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ export const navTabs: NavTabs[] = [
2424
href: '/',
2525
},
2626
{
27-
id: 'management',
28-
name: i18n.translate('xpack.endpoint.headerNav.management', {
29-
defaultMessage: 'Management',
27+
id: 'hosts',
28+
name: i18n.translate('xpack.endpoint.headerNav.hosts', {
29+
defaultMessage: 'Hosts',
3030
}),
31-
href: '/management',
31+
href: '/hosts',
3232
},
3333
{
3434
id: 'alerts',

x-pack/plugins/endpoint/public/applications/endpoint/index.tsx

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
1111
import { Route, Switch, BrowserRouter } from 'react-router-dom';
1212
import { Provider } from 'react-redux';
1313
import { Store } from 'redux';
14+
import { useObservable } from 'react-use';
1415
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
1516
import { RouteCapture } from './view/route_capture';
1617
import { EndpointPluginStartDependencies } from '../../plugin';
1718
import { appStoreFactory } from './store';
1819
import { AlertIndex } from './view/alerts';
19-
import { ManagementList } from './view/managing';
20+
import { HostList } from './view/hosts';
2021
import { PolicyList } from './view/policy';
2122
import { PolicyDetails } from './view/policy';
2223
import { HeaderNavigation } from './components/header_nav';
24+
import { EuiThemeProvider } from '../../../../../legacy/common/eui_styled_components';
2325

2426
/**
2527
* This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle.
@@ -48,43 +50,49 @@ interface RouterProps {
4850
}
4951

5052
const AppRoot: React.FunctionComponent<RouterProps> = React.memo(
51-
({ basename, store, coreStart: { http, notifications }, depsStart: { data } }) => (
52-
<Provider store={store}>
53-
<I18nProvider>
54-
<KibanaContextProvider services={{ http, notifications, data }}>
55-
<BrowserRouter basename={basename}>
56-
<RouteCapture>
57-
<HeaderNavigation basename={basename} />
58-
<Switch>
59-
<Route
60-
exact
61-
path="/"
62-
render={() => (
63-
<h1 data-test-subj="welcomeTitle">
64-
<FormattedMessage
65-
id="xpack.endpoint.welcomeTitle"
66-
defaultMessage="Hello World"
67-
/>
68-
</h1>
69-
)}
70-
/>
71-
<Route path="/management" component={ManagementList} />
72-
<Route path="/alerts" component={AlertIndex} />
73-
<Route path="/policy" exact component={PolicyList} />
74-
<Route path="/policy/:id" exact component={PolicyDetails} />
75-
<Route
76-
render={() => (
77-
<FormattedMessage
78-
id="xpack.endpoint.notFound"
79-
defaultMessage="Page Not Found"
53+
({ basename, store, coreStart: { http, notifications, uiSettings }, depsStart: { data } }) => {
54+
const isDarkMode = useObservable<boolean>(uiSettings.get$('theme:darkMode'));
55+
56+
return (
57+
<Provider store={store}>
58+
<I18nProvider>
59+
<KibanaContextProvider services={{ http, notifications, data }}>
60+
<EuiThemeProvider darkMode={isDarkMode}>
61+
<BrowserRouter basename={basename}>
62+
<RouteCapture>
63+
<HeaderNavigation basename={basename} />
64+
<Switch>
65+
<Route
66+
exact
67+
path="/"
68+
render={() => (
69+
<h1 data-test-subj="welcomeTitle">
70+
<FormattedMessage
71+
id="xpack.endpoint.welcomeTitle"
72+
defaultMessage="Hello World"
73+
/>
74+
</h1>
75+
)}
76+
/>
77+
<Route path="/hosts" component={HostList} />
78+
<Route path="/alerts" component={AlertIndex} />
79+
<Route path="/policy" exact component={PolicyList} />
80+
<Route path="/policy/:id" exact component={PolicyDetails} />
81+
<Route
82+
render={() => (
83+
<FormattedMessage
84+
id="xpack.endpoint.notFound"
85+
defaultMessage="Page Not Found"
86+
/>
87+
)}
8088
/>
81-
)}
82-
/>
83-
</Switch>
84-
</RouteCapture>
85-
</BrowserRouter>
86-
</KibanaContextProvider>
87-
</I18nProvider>
88-
</Provider>
89-
)
89+
</Switch>
90+
</RouteCapture>
91+
</BrowserRouter>
92+
</EuiThemeProvider>
93+
</KibanaContextProvider>
94+
</I18nProvider>
95+
</Provider>
96+
);
97+
}
9098
);

x-pack/plugins/endpoint/public/applications/endpoint/store/action.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import { ManagementAction } from './managing';
7+
import { HostAction } from './hosts';
88
import { AlertAction } from './alerts';
99
import { RoutingAction } from './routing';
1010
import { PolicyListAction } from './policy_list';
1111
import { PolicyDetailsAction } from './policy_details';
1212

1313
export type AppAction =
14-
| ManagementAction
14+
| HostAction
1515
| AlertAction
1616
| RoutingAction
1717
| PolicyListAction
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { HostListPagination, ServerApiError } from '../../types';
8+
import { HostResultList, HostMetadata } from '../../../../../common/types';
9+
10+
interface ServerReturnedHostList {
11+
type: 'serverReturnedHostList';
12+
payload: HostResultList;
13+
}
14+
15+
interface ServerReturnedHostDetails {
16+
type: 'serverReturnedHostDetails';
17+
payload: HostMetadata;
18+
}
19+
20+
interface ServerFailedToReturnHostDetails {
21+
type: 'serverFailedToReturnHostDetails';
22+
payload: ServerApiError;
23+
}
24+
25+
interface UserPaginatedHostList {
26+
type: 'userPaginatedHostList';
27+
payload: HostListPagination;
28+
}
29+
30+
// Why is FakeActionWithNoPayload here, see: https://github.com/elastic/endpoint-app-team/issues/273
31+
interface FakeActionWithNoPayload {
32+
type: 'fakeActionWithNoPayLoad';
33+
}
34+
35+
export type HostAction =
36+
| ServerReturnedHostList
37+
| ServerReturnedHostDetails
38+
| ServerFailedToReturnHostDetails
39+
| UserPaginatedHostList
40+
| FakeActionWithNoPayload;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { createStore, Dispatch, Store } from 'redux';
8+
import { HostAction, hostListReducer } from './index';
9+
import { HostListState } from '../../types';
10+
import { listData } from './selectors';
11+
import { mockHostResultList } from './mock_host_result_list';
12+
13+
describe('HostList store concerns', () => {
14+
let store: Store<HostListState>;
15+
let dispatch: Dispatch<HostAction>;
16+
const createTestStore = () => {
17+
store = createStore(hostListReducer);
18+
dispatch = store.dispatch;
19+
};
20+
21+
const loadDataToStore = () => {
22+
dispatch({
23+
type: 'serverReturnedHostList',
24+
payload: mockHostResultList({ request_page_size: 1, request_page_index: 1, total: 10 }),
25+
});
26+
};
27+
28+
describe('# Reducers', () => {
29+
beforeEach(() => {
30+
createTestStore();
31+
});
32+
33+
test('it creates default state', () => {
34+
expect(store.getState()).toEqual({
35+
hosts: [],
36+
pageSize: 10,
37+
pageIndex: 0,
38+
total: 0,
39+
loading: false,
40+
});
41+
});
42+
43+
test('it handles `serverReturnedHostList', () => {
44+
const payload = mockHostResultList({
45+
request_page_size: 1,
46+
request_page_index: 1,
47+
total: 10,
48+
});
49+
dispatch({
50+
type: 'serverReturnedHostList',
51+
payload,
52+
});
53+
54+
const currentState = store.getState();
55+
expect(currentState.hosts).toEqual(payload.hosts);
56+
expect(currentState.pageSize).toEqual(payload.request_page_size);
57+
expect(currentState.pageIndex).toEqual(payload.request_page_index);
58+
expect(currentState.total).toEqual(payload.total);
59+
});
60+
});
61+
62+
describe('# Selectors', () => {
63+
beforeEach(() => {
64+
createTestStore();
65+
loadDataToStore();
66+
});
67+
68+
test('it selects `hostListData`', () => {
69+
const currentState = store.getState();
70+
expect(listData(currentState)).toEqual(currentState.hosts);
71+
});
72+
});
73+
});

x-pack/plugins/endpoint/public/applications/endpoint/store/managing/index.ts renamed to x-pack/plugins/endpoint/public/applications/endpoint/store/hosts/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
export { managementListReducer } from './reducer';
8-
export { ManagementAction } from './action';
9-
export { managementMiddlewareFactory } from './middleware';
7+
export { hostListReducer } from './reducer';
8+
export { HostAction } from './action';
9+
export { hostMiddlewareFactory } from './middleware';

0 commit comments

Comments
 (0)