Skip to content

Commit b79f5fa

Browse files
yuliacechkibanamachinealisonelizabethjrodewig
authored
Add Managed label to data streams and a view switch for the table (#83049) (#83778)
* Add Managed label to data streams and a view switch for the table * Fix i18n errors * Updated some wording and made filter function easier (managed data streams) * Update x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts Co-authored-by: Alison Goryachev <alisonmllr20@gmail.com> * Renamed view to include (managed data streams) * Update x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com> * Update x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com> * Update x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alison Goryachev <alisonmllr20@gmail.com> Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alison Goryachev <alisonmllr20@gmail.com> Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com>
1 parent 8a8e24b commit b79f5fa

File tree

11 files changed

+182
-29
lines changed

11 files changed

+182
-29
lines changed

x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type TestSubjects =
2121
| 'filterList.filterItem'
2222
| 'ilmPolicyLink'
2323
| 'includeStatsSwitch'
24+
| 'includeManagedSwitch'
2425
| 'indexTable'
2526
| 'indexTableIncludeHiddenIndicesToggle'
2627
| 'indexTableIndexNameLink'

x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface DataStreamsTabTestBed extends TestBed<TestSubjects> {
1919
goToDataStreamsList: () => void;
2020
clickEmptyPromptIndexTemplateLink: () => void;
2121
clickIncludeStatsSwitch: () => void;
22+
clickIncludeManagedSwitch: () => void;
2223
clickReloadButton: () => void;
2324
clickNameAt: (index: number) => void;
2425
clickIndicesAt: (index: number) => void;
@@ -80,6 +81,11 @@ export const setup = async (overridingDependencies: any = {}): Promise<DataStrea
8081
find('includeStatsSwitch').simulate('click');
8182
};
8283

84+
const clickIncludeManagedSwitch = () => {
85+
const { find } = testBed;
86+
find('includeManagedSwitch').simulate('click');
87+
};
88+
8389
const clickReloadButton = () => {
8490
const { find } = testBed;
8591
find('reloadButton').simulate('click');
@@ -183,6 +189,7 @@ export const setup = async (overridingDependencies: any = {}): Promise<DataStrea
183189
goToDataStreamsList,
184190
clickEmptyPromptIndexTemplateLink,
185191
clickIncludeStatsSwitch,
192+
clickIncludeManagedSwitch,
186193
clickReloadButton,
187194
clickNameAt,
188195
clickIndicesAt,
@@ -202,8 +209,8 @@ export const setup = async (overridingDependencies: any = {}): Promise<DataStrea
202209
};
203210
};
204211

205-
export const createDataStreamPayload = (name: string): DataStream => ({
206-
name,
212+
export const createDataStreamPayload = (dataStream: Partial<DataStream>): DataStream => ({
213+
name: 'my-data-stream',
207214
timeStampField: { name: '@timestamp' },
208215
indices: [
209216
{
@@ -216,6 +223,7 @@ export const createDataStreamPayload = (name: string): DataStream => ({
216223
indexTemplateName: 'indexTemplate',
217224
storageSize: '1b',
218225
maxTimeStamp: 420,
226+
...dataStream,
219227
});
220228

221229
export const createDataStreamBackingIndex = (indexName: string, dataStreamName: string) => ({

x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ describe('Data Streams tab', () => {
9999
createNonDataStreamIndex('non-data-stream-index'),
100100
]);
101101

102-
const dataStreamForDetailPanel = createDataStreamPayload('dataStream1');
102+
const dataStreamForDetailPanel = createDataStreamPayload({ name: 'dataStream1' });
103103
setLoadDataStreamsResponse([
104104
dataStreamForDetailPanel,
105-
createDataStreamPayload('dataStream2'),
105+
createDataStreamPayload({ name: 'dataStream2' }),
106106
]);
107107
setLoadDataStreamResponse(dataStreamForDetailPanel);
108108

@@ -287,9 +287,9 @@ describe('Data Streams tab', () => {
287287
createDataStreamBackingIndex('data-stream-index2', 'dataStream2'),
288288
]);
289289

290-
const dataStreamDollarSign = createDataStreamPayload('%dataStream');
291-
setLoadDataStreamsResponse([dataStreamDollarSign]);
292-
setLoadDataStreamResponse(dataStreamDollarSign);
290+
const dataStreamPercentSign = createDataStreamPayload({ name: '%dataStream' });
291+
setLoadDataStreamsResponse([dataStreamPercentSign]);
292+
setLoadDataStreamResponse(dataStreamPercentSign);
293293

294294
testBed = await setup({
295295
history: createMemoryHistory(),
@@ -327,10 +327,10 @@ describe('Data Streams tab', () => {
327327
test('with an ILM url generator and an ILM policy', async () => {
328328
const { setLoadDataStreamsResponse, setLoadDataStreamResponse } = httpRequestsMockHelpers;
329329

330-
const dataStreamForDetailPanel = {
331-
...createDataStreamPayload('dataStream1'),
330+
const dataStreamForDetailPanel = createDataStreamPayload({
331+
name: 'dataStream1',
332332
ilmPolicyName: 'my_ilm_policy',
333-
};
333+
});
334334
setLoadDataStreamsResponse([dataStreamForDetailPanel]);
335335
setLoadDataStreamResponse(dataStreamForDetailPanel);
336336

@@ -351,7 +351,7 @@ describe('Data Streams tab', () => {
351351
test('with an ILM url generator and no ILM policy', async () => {
352352
const { setLoadDataStreamsResponse, setLoadDataStreamResponse } = httpRequestsMockHelpers;
353353

354-
const dataStreamForDetailPanel = createDataStreamPayload('dataStream1');
354+
const dataStreamForDetailPanel = createDataStreamPayload({ name: 'dataStream1' });
355355
setLoadDataStreamsResponse([dataStreamForDetailPanel]);
356356
setLoadDataStreamResponse(dataStreamForDetailPanel);
357357

@@ -373,10 +373,10 @@ describe('Data Streams tab', () => {
373373
test('without an ILM url generator and with an ILM policy', async () => {
374374
const { setLoadDataStreamsResponse, setLoadDataStreamResponse } = httpRequestsMockHelpers;
375375

376-
const dataStreamForDetailPanel = {
377-
...createDataStreamPayload('dataStream1'),
376+
const dataStreamForDetailPanel = createDataStreamPayload({
377+
name: 'dataStream1',
378378
ilmPolicyName: 'my_ilm_policy',
379-
};
379+
});
380380
setLoadDataStreamsResponse([dataStreamForDetailPanel]);
381381
setLoadDataStreamResponse(dataStreamForDetailPanel);
382382

@@ -395,4 +395,58 @@ describe('Data Streams tab', () => {
395395
expect(findDetailPanelIlmPolicyName().contains('my_ilm_policy')).toBeTruthy();
396396
});
397397
});
398+
399+
describe('managed data streams', () => {
400+
const nonBreakingSpace = ' ';
401+
beforeEach(async () => {
402+
const managedDataStream = createDataStreamPayload({
403+
name: 'managed-data-stream',
404+
_meta: {
405+
package: 'test',
406+
managed: true,
407+
managed_by: 'ingest-manager',
408+
},
409+
});
410+
const nonManagedDataStream = createDataStreamPayload({ name: 'non-managed-data-stream' });
411+
httpRequestsMockHelpers.setLoadDataStreamsResponse([managedDataStream, nonManagedDataStream]);
412+
413+
testBed = await setup({
414+
history: createMemoryHistory(),
415+
});
416+
await act(async () => {
417+
testBed.actions.goToDataStreamsList();
418+
});
419+
testBed.component.update();
420+
});
421+
422+
test('listed in the table with Managed label', () => {
423+
const { table } = testBed;
424+
const { tableCellsValues } = table.getMetaData('dataStreamTable');
425+
426+
expect(tableCellsValues).toEqual([
427+
['', `managed-data-stream${nonBreakingSpace}Managed`, 'green', '1', 'Delete'],
428+
['', 'non-managed-data-stream', 'green', '1', 'Delete'],
429+
]);
430+
});
431+
432+
test('turning off "Include managed" switch hides managed data streams', async () => {
433+
const { exists, actions, component, table } = testBed;
434+
let { tableCellsValues } = table.getMetaData('dataStreamTable');
435+
436+
expect(tableCellsValues).toEqual([
437+
['', `managed-data-stream${nonBreakingSpace}Managed`, 'green', '1', 'Delete'],
438+
['', 'non-managed-data-stream', 'green', '1', 'Delete'],
439+
]);
440+
441+
expect(exists('includeManagedSwitch')).toBe(true);
442+
443+
await act(async () => {
444+
actions.clickIncludeManagedSwitch();
445+
});
446+
component.update();
447+
448+
({ tableCellsValues } = table.getMetaData('dataStreamTable'));
449+
expect(tableCellsValues).toEqual([['', 'non-managed-data-stream', 'green', '1', 'Delete']]);
450+
});
451+
});
398452
});

x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ describe('<IndexManagementHome />', () => {
7474
// The detail panel should still appear even if there are no data streams.
7575
httpRequestsMockHelpers.setLoadDataStreamsResponse([]);
7676

77-
httpRequestsMockHelpers.setLoadDataStreamResponse(createDataStreamPayload('dataStream1'));
77+
httpRequestsMockHelpers.setLoadDataStreamResponse(
78+
createDataStreamPayload({ name: 'dataStream1' })
79+
);
7880

7981
testBed = await setup({
8082
history: createMemoryHistory(),

x-pack/plugins/index_management/common/lib/data_stream_serialization.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function deserializeDataStream(dataStreamFromEs: DataStreamFromEs): DataS
1717
ilm_policy: ilmPolicyName,
1818
store_size: storageSize,
1919
maximum_timestamp: maxTimeStamp,
20+
_meta,
2021
} = dataStreamFromEs;
2122

2223
return {
@@ -35,6 +36,7 @@ export function deserializeDataStream(dataStreamFromEs: DataStreamFromEs): DataS
3536
ilmPolicyName,
3637
storageSize,
3738
maxTimeStamp,
39+
_meta,
3840
};
3941
}
4042

x-pack/plugins/index_management/common/types/data_streams.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,22 @@ interface TimestampFieldFromEs {
1010

1111
type TimestampField = TimestampFieldFromEs;
1212

13+
interface MetaFieldFromEs {
14+
managed_by: string;
15+
package: any;
16+
managed: boolean;
17+
}
18+
19+
type MetaField = MetaFieldFromEs;
20+
1321
export type HealthFromEs = 'GREEN' | 'YELLOW' | 'RED';
1422

1523
export interface DataStreamFromEs {
1624
name: string;
1725
timestamp_field: TimestampFieldFromEs;
1826
indices: DataStreamIndexFromEs[];
1927
generation: number;
28+
_meta?: MetaFieldFromEs;
2029
status: HealthFromEs;
2130
template: string;
2231
ilm_policy?: string;
@@ -41,6 +50,7 @@ export interface DataStream {
4150
ilmPolicyName?: string;
4251
storageSize?: string;
4352
maxTimeStamp?: number;
53+
_meta?: MetaField;
4454
}
4555

4656
export interface DataStreamIndex {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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 { DataStream } from '../../../common';
8+
9+
export const isManagedByIngestManager = (dataStream: DataStream): boolean => {
10+
return Boolean(dataStream._meta?.managed && dataStream._meta?.managed_by === 'ingest-manager');
11+
};
12+
13+
export const filterDataStreams = (dataStreams: DataStream[]): DataStream[] => {
14+
return dataStreams.filter((dataStream: DataStream) => !isManagedByIngestManager(dataStream));
15+
};

x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { documentationService } from '../../../services/documentation';
3232
import { Section } from '../home';
3333
import { DataStreamTable } from './data_stream_table';
3434
import { DataStreamDetailPanel } from './data_stream_detail_panel';
35+
import { filterDataStreams } from '../../../lib/data_streams';
3536

3637
interface MatchParams {
3738
dataStreamName?: string;
@@ -52,6 +53,7 @@ export const DataStreamList: React.FunctionComponent<RouteComponentProps<MatchPa
5253
} = useAppContext();
5354

5455
const [isIncludeStatsChecked, setIsIncludeStatsChecked] = useState(false);
56+
const [isIncludeManagedChecked, setIsIncludeManagedChecked] = useState(true);
5557
const { error, isLoading, data: dataStreams, resendRequest: reload } = useLoadDataStreams({
5658
includeStats: isIncludeStatsChecked,
5759
});
@@ -147,11 +149,13 @@ export const DataStreamList: React.FunctionComponent<RouteComponentProps<MatchPa
147149
/>
148150
);
149151
} else if (Array.isArray(dataStreams) && dataStreams.length > 0) {
152+
const filteredDataStreams = isIncludeManagedChecked
153+
? dataStreams
154+
: filterDataStreams(dataStreams);
150155
content = (
151156
<>
152157
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
153158
<EuiFlexItem>
154-
{/* TODO: Add a switch for toggling on data streams created by Ingest Manager */}
155159
<EuiText color="subdued">
156160
<FormattedMessage
157161
id="xpack.idxMgmt.dataStreamList.dataStreamsDescription"
@@ -202,6 +206,35 @@ export const DataStreamList: React.FunctionComponent<RouteComponentProps<MatchPa
202206
</EuiFlexItem>
203207
</EuiFlexGroup>
204208
</EuiFlexItem>
209+
<EuiFlexItem grow={false}>
210+
<EuiFlexGroup gutterSize="s">
211+
<EuiFlexItem grow={false}>
212+
<EuiSwitch
213+
label={i18n.translate(
214+
'xpack.idxMgmt.dataStreamListControls.includeManagedSwitchLabel',
215+
{
216+
defaultMessage: 'Include Fleet-managed streams',
217+
}
218+
)}
219+
checked={isIncludeManagedChecked}
220+
onChange={(e) => setIsIncludeManagedChecked(e.target.checked)}
221+
data-test-subj="includeManagedSwitch"
222+
/>
223+
</EuiFlexItem>
224+
225+
<EuiFlexItem grow={false}>
226+
<EuiIconTip
227+
content={i18n.translate(
228+
'xpack.idxMgmt.dataStreamListControls.includeManagedSwitchToolTip',
229+
{
230+
defaultMessage: 'Display data streams managed by Fleet',
231+
}
232+
)}
233+
position="top"
234+
/>
235+
</EuiFlexItem>
236+
</EuiFlexGroup>
237+
</EuiFlexItem>
205238
</EuiFlexGroup>
206239

207240
<EuiSpacer size="l" />
@@ -212,7 +245,7 @@ export const DataStreamList: React.FunctionComponent<RouteComponentProps<MatchPa
212245
? `name="${attemptToURIDecode(dataStreamName)}"`
213246
: ''
214247
}
215-
dataStreams={dataStreams}
248+
dataStreams={filteredDataStreams}
216249
reload={reload}
217250
history={history as ScopedHistory}
218251
includeStats={isIncludeStatsChecked}

0 commit comments

Comments
 (0)