Skip to content

Commit

Permalink
[SECURITY_SOLUTION] list UI is backwards compatible (#77956) (#78108)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinlog authored Sep 22, 2020
1 parent afc0c1e commit caa32b2
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ describe('EndpointList store concerns', () => {
patternsError: undefined,
isAutoRefreshEnabled: true,
autoRefreshInterval: DEFAULT_POLL_INTERVAL,
queryStrategyVersion: undefined,
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
nonExistingPolicies,
patterns,
searchBarQuery,
isTransformEnabled,
} from './selectors';
import { EndpointState, PolicyIds } from '../types';
import {
Expand Down Expand Up @@ -70,24 +71,6 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory<EndpointState
const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(getState());
let endpointResponse;

// get index pattern and fields for search bar
if (patterns(getState()).length === 0) {
try {
const indexPatterns = await fetchIndexPatterns();
if (indexPatterns !== undefined) {
dispatch({
type: 'serverReturnedMetadataPatterns',
payload: indexPatterns,
});
}
} catch (error) {
dispatch({
type: 'serverFailedToReturnMetadataPatterns',
payload: error,
});
}
}

try {
const decodedQuery: Query = searchBarQuery(getState());

Expand Down Expand Up @@ -134,6 +117,24 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory<EndpointState
});
}

// get index pattern and fields for search bar
if (patterns(getState()).length === 0 && isTransformEnabled(getState())) {
try {
const indexPatterns = await fetchIndexPatterns();
if (indexPatterns !== undefined) {
dispatch({
type: 'serverReturnedMetadataPatterns',
payload: indexPatterns,
});
}
} catch (error) {
dispatch({
type: 'serverFailedToReturnMetadataPatterns',
payload: error,
});
}
}

// No endpoints, so we should check to see if there are policies for onboarding
if (endpointResponse && endpointResponse.hosts.length === 0) {
const http = coreStart.http;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ export const mockEndpointResultList: (options?: {
total?: number;
request_page_size?: number;
request_page_index?: number;
query_strategy_version?: MetadataQueryStrategyVersions;
}) => HostResultList = (options = {}) => {
const {
total = 1,
request_page_size: requestPageSize = 10,
request_page_index: requestPageIndex = 0,
query_strategy_version: queryStrategyVersion = MetadataQueryStrategyVersions.VERSION_2,
} = options;

// Skip any that are before the page we're on
Expand All @@ -50,15 +52,15 @@ export const mockEndpointResultList: (options?: {
hosts.push({
metadata: generator.generateHostMetadata(),
host_status: HostStatus.ERROR,
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
query_strategy_version: queryStrategyVersion,
});
}
const mock: HostResultList = {
hosts,
total,
request_page_size: requestPageSize,
request_page_index: requestPageIndex,
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
query_strategy_version: queryStrategyVersion,
};
return mock;
};
Expand All @@ -84,13 +86,15 @@ const endpointListApiPathHandlerMocks = ({
endpointPackagePolicies = [],
policyResponse = generator.generatePolicyResponse(),
agentPolicy = generator.generateAgentPolicy(),
queryStrategyVersion = MetadataQueryStrategyVersions.VERSION_2,
}: {
/** route handlers will be setup for each individual host in this array */
endpointsResults?: HostResultList['hosts'];
epmPackages?: GetPackagesResponse['response'];
endpointPackagePolicies?: GetPolicyListResponse['items'];
policyResponse?: HostPolicyResponse;
agentPolicy?: GetAgentPoliciesResponseItem;
queryStrategyVersion?: MetadataQueryStrategyVersions;
} = {}) => {
const apiHandlers = {
// endpoint package info
Expand All @@ -107,7 +111,7 @@ const endpointListApiPathHandlerMocks = ({
request_page_size: 10,
request_page_index: 0,
total: endpointsResults?.length || 0,
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
query_strategy_version: queryStrategyVersion,
};
},

Expand Down Expand Up @@ -164,11 +168,16 @@ export const setEndpointListApiMockImplementation: (
apiResponses?: Parameters<typeof endpointListApiPathHandlerMocks>[0]
) => void = (
mockedHttpService,
{ endpointsResults = mockEndpointResultList({ total: 3 }).hosts, ...pathHandlersOptions } = {}
{
endpointsResults = mockEndpointResultList({ total: 3 }).hosts,
queryStrategyVersion = MetadataQueryStrategyVersions.VERSION_2,
...pathHandlersOptions
} = {}
) => {
const apiHandlers = endpointListApiPathHandlerMocks({
...pathHandlersOptions,
endpointsResults,
queryStrategyVersion,
});

mockedHttpService.post
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const initialEndpointListState: Immutable<EndpointState> = {
patternsError: undefined,
isAutoRefreshEnabled: true,
autoRefreshInterval: DEFAULT_POLL_INTERVAL,
queryStrategyVersion: undefined,
};

/* eslint-disable-next-line complexity */
Expand All @@ -49,13 +50,15 @@ export const endpointListReducer: ImmutableReducer<EndpointState, AppAction> = (
total,
request_page_size: pageSize,
request_page_index: pageIndex,
query_strategy_version: queryStrategyVersion,
} = action.payload;
return {
...state,
hosts,
total,
pageSize,
pageIndex,
queryStrategyVersion,
loading: false,
error: undefined,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
HostPolicyResponseAppliedAction,
HostPolicyResponseConfiguration,
HostPolicyResponseActionStatus,
MetadataQueryStrategyVersions,
} from '../../../../../common/endpoint/types';
import { EndpointState, EndpointIndexUIQueryParams } from '../types';
import { extractListPaginationParams } from '../../../common/routing';
Expand Down Expand Up @@ -54,11 +55,18 @@ export const isAutoRefreshEnabled = (state: Immutable<EndpointState>) => state.i

export const autoRefreshInterval = (state: Immutable<EndpointState>) => state.autoRefreshInterval;

const queryStrategyVersion = (state: Immutable<EndpointState>) => state.queryStrategyVersion;

export const endpointPackageVersion = createSelector(
endpointPackageInfo,
(info) => info?.version ?? undefined
);

export const isTransformEnabled = createSelector(
queryStrategyVersion,
(version) => version !== MetadataQueryStrategyVersions.VERSION_1
);

/**
* Returns the index patterns for the SearchBar to use for autosuggest
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
HostPolicyResponse,
AppLocation,
PolicyData,
MetadataQueryStrategyVersions,
} from '../../../../common/endpoint/types';
import { ServerApiError } from '../../../common/types';
import { GetPackagesResponse } from '../../../../../ingest_manager/common';
Expand Down Expand Up @@ -65,6 +66,8 @@ export interface EndpointState {
isAutoRefreshEnabled: boolean;
/** The current auto refresh interval for data in ms */
autoRefreshInterval: number;
/** The query strategy version that informs whether the transform for KQL is enabled or not */
queryStrategyVersion?: MetadataQueryStrategyVersions;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,31 @@ describe('when on the list page', () => {
});
});

describe('when loading data with the query_strategy_version is `v1`', () => {
beforeEach(() => {
reactTestingLibrary.act(() => {
const mockedEndpointListData = mockEndpointResultList({
total: 4,
query_strategy_version: MetadataQueryStrategyVersions.VERSION_1,
});
setEndpointListApiMockImplementation(coreStart.http, {
endpointsResults: mockedEndpointListData.hosts,
queryStrategyVersion: mockedEndpointListData.query_strategy_version,
});
});
});
afterEach(() => {
jest.clearAllMocks();
});
it('should not display the KQL bar', async () => {
const renderResult = render();
await reactTestingLibrary.act(async () => {
await middlewareSpy.waitForAction('serverReturnedEndpointList');
});
expect(renderResult.queryByTestId('adminSearchBar')).toBeNull();
});
});

describe('when there is no selected host in the url', () => {
it('should not show the flyout', () => {
const renderResult = render();
Expand All @@ -123,7 +148,9 @@ describe('when on the list page', () => {
let firstPolicyID: string;
beforeEach(() => {
reactTestingLibrary.act(() => {
const hostListData = mockEndpointResultList({ total: 4 }).hosts;
const mockedEndpointData = mockEndpointResultList({ total: 4 });
const hostListData = mockedEndpointData.hosts;
const queryStrategyVersion = mockedEndpointData.query_strategy_version;

firstPolicyID = hostListData[0].metadata.Endpoint.policy.applied.id;

Expand All @@ -132,7 +159,7 @@ describe('when on the list page', () => {
hostListData[index] = {
metadata: hostListData[index].metadata,
host_status: status,
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
query_strategy_version: queryStrategyVersion,
};
}
);
Expand Down Expand Up @@ -682,11 +709,11 @@ describe('when on the list page', () => {
let renderAndWaitForData: () => Promise<ReturnType<AppContextTestRender['render']>>;

const mockEndpointListApi = () => {
const { hosts } = mockEndpointResultList();
const { hosts, query_strategy_version: queryStrategyVersion } = mockEndpointResultList();
hostInfo = {
host_status: hosts[0].host_status,
metadata: hosts[0].metadata,
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
query_strategy_version: queryStrategyVersion,
};
const packagePolicy = docGenerator.generatePolicyPackagePolicy();
packagePolicy.id = hosts[0].metadata.Endpoint.policy.applied.id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const EndpointList = () => {
autoRefreshInterval,
isAutoRefreshEnabled,
patternsError,
isTransformEnabled,
} = useEndpointSelector(selector);
const { formatUrl, search } = useFormatUrl(SecurityPageName.administration);

Expand Down Expand Up @@ -532,8 +533,8 @@ export const EndpointList = () => {
const hasListData = listData && listData.length > 0;

const refreshStyle = useMemo(() => {
return { display: endpointsExist ? 'flex' : 'none', maxWidth: 200 };
}, [endpointsExist]);
return { display: endpointsExist && isTransformEnabled ? 'flex' : 'none', maxWidth: 200 };
}, [endpointsExist, isTransformEnabled]);

const refreshIsPaused = useMemo(() => {
return !endpointsExist ? false : hasSelectedEndpoint ? true : !isAutoRefreshEnabled;
Expand All @@ -543,6 +544,10 @@ export const EndpointList = () => {
return !endpointsExist ? DEFAULT_POLL_INTERVAL : autoRefreshInterval;
}, [endpointsExist, autoRefreshInterval]);

const shouldShowKQLBar = useMemo(() => {
return endpointsExist && !patternsError && isTransformEnabled;
}, [endpointsExist, patternsError, isTransformEnabled]);

return (
<AdministrationListPage
data-test-subj="endpointPage"
Expand All @@ -563,7 +568,7 @@ export const EndpointList = () => {
{hasSelectedEndpoint && <EndpointDetailsFlyout />}
<>
<EuiFlexGroup>
{endpointsExist && !patternsError && (
{shouldShowKQLBar && (
<EuiFlexItem>
<AdminSearchBar />
</EuiFlexItem>
Expand Down

0 comments on commit caa32b2

Please sign in to comment.