Skip to content

Commit

Permalink
Task/host enhancements (#59671)
Browse files Browse the repository at this point in the history
functional tests and ui updates to endpoint host details
  • Loading branch information
parkiino authored Mar 18, 2020
1 parent ac5e323 commit 65a111f
Show file tree
Hide file tree
Showing 36 changed files with 623 additions and 545 deletions.
12 changes: 6 additions & 6 deletions x-pack/plugins/endpoint/common/generate_data.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ describe('data generator', () => {
const generator1 = new EndpointDocGenerator('seed');
const generator2 = new EndpointDocGenerator('seed');
const timestamp = new Date().getTime();
const metadata1 = generator1.generateEndpointMetadata(timestamp);
const metadata2 = generator2.generateEndpointMetadata(timestamp);
const metadata1 = generator1.generateHostMetadata(timestamp);
const metadata2 = generator2.generateHostMetadata(timestamp);
expect(metadata1).toEqual(metadata2);
});

it('creates different documents with different random seeds', () => {
const generator1 = new EndpointDocGenerator('seed');
const generator2 = new EndpointDocGenerator('different seed');
const timestamp = new Date().getTime();
const metadata1 = generator1.generateEndpointMetadata(timestamp);
const metadata2 = generator2.generateEndpointMetadata(timestamp);
const metadata1 = generator1.generateHostMetadata(timestamp);
const metadata2 = generator2.generateHostMetadata(timestamp);
expect(metadata1).not.toEqual(metadata2);
});

it('creates endpoint metadata documents', () => {
it('creates host metadata documents', () => {
const timestamp = new Date().getTime();
const metadata = generator.generateEndpointMetadata(timestamp);
const metadata = generator.generateHostMetadata(timestamp);
expect(metadata['@timestamp']).toEqual(timestamp);
expect(metadata.event.created).toEqual(timestamp);
expect(metadata.endpoint).not.toBeNull();
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/endpoint/common/generate_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import uuid from 'uuid';
import seedrandom from 'seedrandom';
import { AlertEvent, EndpointEvent, EndpointMetadata, OSFields, HostFields } from './types';
import { AlertEvent, EndpointEvent, HostMetadata, OSFields, HostFields } from './types';

export type Event = AlertEvent | EndpointEvent;

Expand Down Expand Up @@ -104,8 +104,8 @@ export class EndpointDocGenerator {
this.commonInfo = this.createHostData();
}

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

public generateEndpointMetadata(ts = new Date().getTime()): EndpointMetadata {
public generateHostMetadata(ts = new Date().getTime()): HostMetadata {
return {
'@timestamp': ts,
event: {
Expand Down
12 changes: 6 additions & 6 deletions x-pack/plugins/endpoint/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ export interface AlertResultList {
prev: string | null;
}

export interface EndpointResultList {
/* the endpoints restricted by the page size */
endpoints: EndpointMetadata[];
/* the total number of unique endpoints in the index */
export interface HostResultList {
/* the hosts restricted by the page size */
hosts: HostMetadata[];
/* the total number of unique hosts in the index */
total: number;
/* the page size requested */
request_page_size: number;
Expand Down Expand Up @@ -243,7 +243,7 @@ interface AlertMetadata {
*/
export type AlertData = AlertEvent & AlertMetadata;

export interface EndpointMetadata {
export type HostMetadata = Immutable<{
'@timestamp': number;
event: {
created: number;
Expand All @@ -258,7 +258,7 @@ export interface EndpointMetadata {
version: string;
};
host: HostFields;
}
}>;

/**
* Represents `total` response from Elasticsearch after ES 7.0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ export const navTabs: NavTabs[] = [
href: '/',
},
{
id: 'management',
name: i18n.translate('xpack.endpoint.headerNav.management', {
defaultMessage: 'Management',
id: 'hosts',
name: i18n.translate('xpack.endpoint.headerNav.hosts', {
defaultMessage: 'Hosts',
}),
href: '/management',
href: '/hosts',
},
{
id: 'alerts',
Expand Down
86 changes: 47 additions & 39 deletions x-pack/plugins/endpoint/public/applications/endpoint/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
import { Route, Switch, BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { Store } from 'redux';
import { useObservable } from 'react-use';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import { RouteCapture } from './view/route_capture';
import { EndpointPluginStartDependencies } from '../../plugin';
import { appStoreFactory } from './store';
import { AlertIndex } from './view/alerts';
import { ManagementList } from './view/managing';
import { HostList } from './view/hosts';
import { PolicyList } from './view/policy';
import { PolicyDetails } from './view/policy';
import { HeaderNavigation } from './components/header_nav';
import { EuiThemeProvider } from '../../../../../legacy/common/eui_styled_components';

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

const AppRoot: React.FunctionComponent<RouterProps> = React.memo(
({ basename, store, coreStart: { http, notifications }, depsStart: { data } }) => (
<Provider store={store}>
<I18nProvider>
<KibanaContextProvider services={{ http, notifications, data }}>
<BrowserRouter basename={basename}>
<RouteCapture>
<HeaderNavigation basename={basename} />
<Switch>
<Route
exact
path="/"
render={() => (
<h1 data-test-subj="welcomeTitle">
<FormattedMessage
id="xpack.endpoint.welcomeTitle"
defaultMessage="Hello World"
/>
</h1>
)}
/>
<Route path="/management" component={ManagementList} />
<Route path="/alerts" component={AlertIndex} />
<Route path="/policy" exact component={PolicyList} />
<Route path="/policy/:id" exact component={PolicyDetails} />
<Route
render={() => (
<FormattedMessage
id="xpack.endpoint.notFound"
defaultMessage="Page Not Found"
({ basename, store, coreStart: { http, notifications, uiSettings }, depsStart: { data } }) => {
const isDarkMode = useObservable<boolean>(uiSettings.get$('theme:darkMode'));

return (
<Provider store={store}>
<I18nProvider>
<KibanaContextProvider services={{ http, notifications, data }}>
<EuiThemeProvider darkMode={isDarkMode}>
<BrowserRouter basename={basename}>
<RouteCapture>
<HeaderNavigation basename={basename} />
<Switch>
<Route
exact
path="/"
render={() => (
<h1 data-test-subj="welcomeTitle">
<FormattedMessage
id="xpack.endpoint.welcomeTitle"
defaultMessage="Hello World"
/>
</h1>
)}
/>
<Route path="/hosts" component={HostList} />
<Route path="/alerts" component={AlertIndex} />
<Route path="/policy" exact component={PolicyList} />
<Route path="/policy/:id" exact component={PolicyDetails} />
<Route
render={() => (
<FormattedMessage
id="xpack.endpoint.notFound"
defaultMessage="Page Not Found"
/>
)}
/>
)}
/>
</Switch>
</RouteCapture>
</BrowserRouter>
</KibanaContextProvider>
</I18nProvider>
</Provider>
)
</Switch>
</RouteCapture>
</BrowserRouter>
</EuiThemeProvider>
</KibanaContextProvider>
</I18nProvider>
</Provider>
);
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ManagementAction } from './managing';
import { HostAction } from './hosts';
import { AlertAction } from './alerts';
import { RoutingAction } from './routing';
import { PolicyListAction } from './policy_list';
import { PolicyDetailsAction } from './policy_details';

export type AppAction =
| ManagementAction
| HostAction
| AlertAction
| RoutingAction
| PolicyListAction
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
* you may not use this file except in compliance with the Elastic License.
*/

import { HostListPagination, ServerApiError } from '../../types';
import { HostResultList, HostMetadata } from '../../../../../common/types';

interface ServerReturnedHostList {
type: 'serverReturnedHostList';
payload: HostResultList;
}

interface ServerReturnedHostDetails {
type: 'serverReturnedHostDetails';
payload: HostMetadata;
}

interface ServerFailedToReturnHostDetails {
type: 'serverFailedToReturnHostDetails';
payload: ServerApiError;
}

interface UserPaginatedHostList {
type: 'userPaginatedHostList';
payload: HostListPagination;
}

// Why is FakeActionWithNoPayload here, see: https://github.com/elastic/endpoint-app-team/issues/273
interface FakeActionWithNoPayload {
type: 'fakeActionWithNoPayLoad';
}

export type HostAction =
| ServerReturnedHostList
| ServerReturnedHostDetails
| ServerFailedToReturnHostDetails
| UserPaginatedHostList
| FakeActionWithNoPayload;
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* 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 { createStore, Dispatch, Store } from 'redux';
import { HostAction, hostListReducer } from './index';
import { HostListState } from '../../types';
import { listData } from './selectors';
import { mockHostResultList } from './mock_host_result_list';

describe('HostList store concerns', () => {
let store: Store<HostListState>;
let dispatch: Dispatch<HostAction>;
const createTestStore = () => {
store = createStore(hostListReducer);
dispatch = store.dispatch;
};

const loadDataToStore = () => {
dispatch({
type: 'serverReturnedHostList',
payload: mockHostResultList({ request_page_size: 1, request_page_index: 1, total: 10 }),
});
};

describe('# Reducers', () => {
beforeEach(() => {
createTestStore();
});

test('it creates default state', () => {
expect(store.getState()).toEqual({
hosts: [],
pageSize: 10,
pageIndex: 0,
total: 0,
loading: false,
});
});

test('it handles `serverReturnedHostList', () => {
const payload = mockHostResultList({
request_page_size: 1,
request_page_index: 1,
total: 10,
});
dispatch({
type: 'serverReturnedHostList',
payload,
});

const currentState = store.getState();
expect(currentState.hosts).toEqual(payload.hosts);
expect(currentState.pageSize).toEqual(payload.request_page_size);
expect(currentState.pageIndex).toEqual(payload.request_page_index);
expect(currentState.total).toEqual(payload.total);
});
});

describe('# Selectors', () => {
beforeEach(() => {
createTestStore();
loadDataToStore();
});

test('it selects `hostListData`', () => {
const currentState = store.getState();
expect(listData(currentState)).toEqual(currentState.hosts);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

export { managementListReducer } from './reducer';
export { ManagementAction } from './action';
export { managementMiddlewareFactory } from './middleware';
export { hostListReducer } from './reducer';
export { HostAction } from './action';
export { hostMiddlewareFactory } from './middleware';
Loading

0 comments on commit 65a111f

Please sign in to comment.