Skip to content

Commit bde8793

Browse files
committed
[SECURITY_SOLUTION] list UI is backwards compatible (#77956)
1 parent be7ae56 commit bde8793

8 files changed

Lines changed: 86 additions & 29 deletions

File tree

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ describe('EndpointList store concerns', () => {
5858
patternsError: undefined,
5959
isAutoRefreshEnabled: true,
6060
autoRefreshInterval: DEFAULT_POLL_INTERVAL,
61+
queryStrategyVersion: undefined,
6162
});
6263
});
6364

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
nonExistingPolicies,
1818
patterns,
1919
searchBarQuery,
20+
isTransformEnabled,
2021
} from './selectors';
2122
import { EndpointState, PolicyIds } from '../types';
2223
import {
@@ -70,24 +71,6 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory<EndpointState
7071
const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(getState());
7172
let endpointResponse;
7273

73-
// get index pattern and fields for search bar
74-
if (patterns(getState()).length === 0) {
75-
try {
76-
const indexPatterns = await fetchIndexPatterns();
77-
if (indexPatterns !== undefined) {
78-
dispatch({
79-
type: 'serverReturnedMetadataPatterns',
80-
payload: indexPatterns,
81-
});
82-
}
83-
} catch (error) {
84-
dispatch({
85-
type: 'serverFailedToReturnMetadataPatterns',
86-
payload: error,
87-
});
88-
}
89-
}
90-
9174
try {
9275
const decodedQuery: Query = searchBarQuery(getState());
9376

@@ -134,6 +117,24 @@ export const endpointMiddlewareFactory: ImmutableMiddlewareFactory<EndpointState
134117
});
135118
}
136119

120+
// get index pattern and fields for search bar
121+
if (patterns(getState()).length === 0 && isTransformEnabled(getState())) {
122+
try {
123+
const indexPatterns = await fetchIndexPatterns();
124+
if (indexPatterns !== undefined) {
125+
dispatch({
126+
type: 'serverReturnedMetadataPatterns',
127+
payload: indexPatterns,
128+
});
129+
}
130+
} catch (error) {
131+
dispatch({
132+
type: 'serverFailedToReturnMetadataPatterns',
133+
payload: error,
134+
});
135+
}
136+
}
137+
137138
// No endpoints, so we should check to see if there are policies for onboarding
138139
if (endpointResponse && endpointResponse.hosts.length === 0) {
139140
const http = coreStart.http;

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ export const mockEndpointResultList: (options?: {
3232
total?: number;
3333
request_page_size?: number;
3434
request_page_index?: number;
35+
query_strategy_version?: MetadataQueryStrategyVersions;
3536
}) => HostResultList = (options = {}) => {
3637
const {
3738
total = 1,
3839
request_page_size: requestPageSize = 10,
3940
request_page_index: requestPageIndex = 0,
41+
query_strategy_version: queryStrategyVersion = MetadataQueryStrategyVersions.VERSION_2,
4042
} = options;
4143

4244
// Skip any that are before the page we're on
@@ -50,15 +52,15 @@ export const mockEndpointResultList: (options?: {
5052
hosts.push({
5153
metadata: generator.generateHostMetadata(),
5254
host_status: HostStatus.ERROR,
53-
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
55+
query_strategy_version: queryStrategyVersion,
5456
});
5557
}
5658
const mock: HostResultList = {
5759
hosts,
5860
total,
5961
request_page_size: requestPageSize,
6062
request_page_index: requestPageIndex,
61-
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
63+
query_strategy_version: queryStrategyVersion,
6264
};
6365
return mock;
6466
};
@@ -84,13 +86,15 @@ const endpointListApiPathHandlerMocks = ({
8486
endpointPackagePolicies = [],
8587
policyResponse = generator.generatePolicyResponse(),
8688
agentPolicy = generator.generateAgentPolicy(),
89+
queryStrategyVersion = MetadataQueryStrategyVersions.VERSION_2,
8790
}: {
8891
/** route handlers will be setup for each individual host in this array */
8992
endpointsResults?: HostResultList['hosts'];
9093
epmPackages?: GetPackagesResponse['response'];
9194
endpointPackagePolicies?: GetPolicyListResponse['items'];
9295
policyResponse?: HostPolicyResponse;
9396
agentPolicy?: GetAgentPoliciesResponseItem;
97+
queryStrategyVersion?: MetadataQueryStrategyVersions;
9498
} = {}) => {
9599
const apiHandlers = {
96100
// endpoint package info
@@ -107,7 +111,7 @@ const endpointListApiPathHandlerMocks = ({
107111
request_page_size: 10,
108112
request_page_index: 0,
109113
total: endpointsResults?.length || 0,
110-
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
114+
query_strategy_version: queryStrategyVersion,
111115
};
112116
},
113117

@@ -164,11 +168,16 @@ export const setEndpointListApiMockImplementation: (
164168
apiResponses?: Parameters<typeof endpointListApiPathHandlerMocks>[0]
165169
) => void = (
166170
mockedHttpService,
167-
{ endpointsResults = mockEndpointResultList({ total: 3 }).hosts, ...pathHandlersOptions } = {}
171+
{
172+
endpointsResults = mockEndpointResultList({ total: 3 }).hosts,
173+
queryStrategyVersion = MetadataQueryStrategyVersions.VERSION_2,
174+
...pathHandlersOptions
175+
} = {}
168176
) => {
169177
const apiHandlers = endpointListApiPathHandlerMocks({
170178
...pathHandlersOptions,
171179
endpointsResults,
180+
queryStrategyVersion,
172181
});
173182

174183
mockedHttpService.post

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/reducer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const initialEndpointListState: Immutable<EndpointState> = {
3636
patternsError: undefined,
3737
isAutoRefreshEnabled: true,
3838
autoRefreshInterval: DEFAULT_POLL_INTERVAL,
39+
queryStrategyVersion: undefined,
3940
};
4041

4142
/* eslint-disable-next-line complexity */
@@ -49,13 +50,15 @@ export const endpointListReducer: ImmutableReducer<EndpointState, AppAction> = (
4950
total,
5051
request_page_size: pageSize,
5152
request_page_index: pageIndex,
53+
query_strategy_version: queryStrategyVersion,
5254
} = action.payload;
5355
return {
5456
...state,
5557
hosts,
5658
total,
5759
pageSize,
5860
pageIndex,
61+
queryStrategyVersion,
5962
loading: false,
6063
error: undefined,
6164
};

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/selectors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
HostPolicyResponseAppliedAction,
1515
HostPolicyResponseConfiguration,
1616
HostPolicyResponseActionStatus,
17+
MetadataQueryStrategyVersions,
1718
} from '../../../../../common/endpoint/types';
1819
import { EndpointState, EndpointIndexUIQueryParams } from '../types';
1920
import { extractListPaginationParams } from '../../../common/routing';
@@ -54,11 +55,18 @@ export const isAutoRefreshEnabled = (state: Immutable<EndpointState>) => state.i
5455

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

58+
const queryStrategyVersion = (state: Immutable<EndpointState>) => state.queryStrategyVersion;
59+
5760
export const endpointPackageVersion = createSelector(
5861
endpointPackageInfo,
5962
(info) => info?.version ?? undefined
6063
);
6164

65+
export const isTransformEnabled = createSelector(
66+
queryStrategyVersion,
67+
(version) => version !== MetadataQueryStrategyVersions.VERSION_1
68+
);
69+
6270
/**
6371
* Returns the index patterns for the SearchBar to use for autosuggest
6472
*/

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
HostPolicyResponse,
1212
AppLocation,
1313
PolicyData,
14+
MetadataQueryStrategyVersions,
1415
} from '../../../../common/endpoint/types';
1516
import { ServerApiError } from '../../../common/types';
1617
import { GetPackagesResponse } from '../../../../../ingest_manager/common';
@@ -65,6 +66,8 @@ export interface EndpointState {
6566
isAutoRefreshEnabled: boolean;
6667
/** The current auto refresh interval for data in ms */
6768
autoRefreshInterval: number;
69+
/** The query strategy version that informs whether the transform for KQL is enabled or not */
70+
queryStrategyVersion?: MetadataQueryStrategyVersions;
6871
}
6972

7073
/**

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,31 @@ describe('when on the list page', () => {
108108
});
109109
});
110110

111+
describe('when loading data with the query_strategy_version is `v1`', () => {
112+
beforeEach(() => {
113+
reactTestingLibrary.act(() => {
114+
const mockedEndpointListData = mockEndpointResultList({
115+
total: 4,
116+
query_strategy_version: MetadataQueryStrategyVersions.VERSION_1,
117+
});
118+
setEndpointListApiMockImplementation(coreStart.http, {
119+
endpointsResults: mockedEndpointListData.hosts,
120+
queryStrategyVersion: mockedEndpointListData.query_strategy_version,
121+
});
122+
});
123+
});
124+
afterEach(() => {
125+
jest.clearAllMocks();
126+
});
127+
it('should not display the KQL bar', async () => {
128+
const renderResult = render();
129+
await reactTestingLibrary.act(async () => {
130+
await middlewareSpy.waitForAction('serverReturnedEndpointList');
131+
});
132+
expect(renderResult.queryByTestId('adminSearchBar')).toBeNull();
133+
});
134+
});
135+
111136
describe('when there is no selected host in the url', () => {
112137
it('should not show the flyout', () => {
113138
const renderResult = render();
@@ -123,7 +148,9 @@ describe('when on the list page', () => {
123148
let firstPolicyID: string;
124149
beforeEach(() => {
125150
reactTestingLibrary.act(() => {
126-
const hostListData = mockEndpointResultList({ total: 4 }).hosts;
151+
const mockedEndpointData = mockEndpointResultList({ total: 4 });
152+
const hostListData = mockedEndpointData.hosts;
153+
const queryStrategyVersion = mockedEndpointData.query_strategy_version;
127154

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

@@ -132,7 +159,7 @@ describe('when on the list page', () => {
132159
hostListData[index] = {
133160
metadata: hostListData[index].metadata,
134161
host_status: status,
135-
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
162+
query_strategy_version: queryStrategyVersion,
136163
};
137164
}
138165
);
@@ -682,11 +709,11 @@ describe('when on the list page', () => {
682709
let renderAndWaitForData: () => Promise<ReturnType<AppContextTestRender['render']>>;
683710

684711
const mockEndpointListApi = () => {
685-
const { hosts } = mockEndpointResultList();
712+
const { hosts, query_strategy_version: queryStrategyVersion } = mockEndpointResultList();
686713
hostInfo = {
687714
host_status: hosts[0].host_status,
688715
metadata: hosts[0].metadata,
689-
query_strategy_version: MetadataQueryStrategyVersions.VERSION_2,
716+
query_strategy_version: queryStrategyVersion,
690717
};
691718
const packagePolicy = docGenerator.generatePolicyPackagePolicy();
692719
packagePolicy.id = hosts[0].metadata.Endpoint.policy.applied.id;

x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ export const EndpointList = () => {
135135
autoRefreshInterval,
136136
isAutoRefreshEnabled,
137137
patternsError,
138+
isTransformEnabled,
138139
} = useEndpointSelector(selector);
139140
const { formatUrl, search } = useFormatUrl(SecurityPageName.administration);
140141

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

534535
const refreshStyle = useMemo(() => {
535-
return { display: endpointsExist ? 'flex' : 'none', maxWidth: 200 };
536-
}, [endpointsExist]);
536+
return { display: endpointsExist && isTransformEnabled ? 'flex' : 'none', maxWidth: 200 };
537+
}, [endpointsExist, isTransformEnabled]);
537538

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

547+
const shouldShowKQLBar = useMemo(() => {
548+
return endpointsExist && !patternsError && isTransformEnabled;
549+
}, [endpointsExist, patternsError, isTransformEnabled]);
550+
546551
return (
547552
<AdministrationListPage
548553
data-test-subj="endpointPage"
@@ -563,7 +568,7 @@ export const EndpointList = () => {
563568
{hasSelectedEndpoint && <EndpointDetailsFlyout />}
564569
<>
565570
<EuiFlexGroup>
566-
{endpointsExist && !patternsError && (
571+
{shouldShowKQLBar && (
567572
<EuiFlexItem>
568573
<AdminSearchBar />
569574
</EuiFlexItem>

0 commit comments

Comments
 (0)