Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SECURITY_SOLUTION] list UI is backwards compatible #77956

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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