Skip to content

Commit ecbdb51

Browse files
[Reporting] ILM policy for managing reporting indices (#100130) (#100562)
* wip; added logic for creating ILM policy at start up * added log when ilm policy is not created * added test for start function * updated ilm policy to not delete data * actually update jest snapshots and remove unused import * updated the ilm policy, removed the min_age for the hot phase * update jest snapshot * removed TODO comment * debug log -> info log Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> # Conflicts: # x-pack/plugins/reporting/server/lib/store/store.test.ts # x-pack/plugins/reporting/server/lib/store/store.ts
1 parent 8ee2bfc commit ecbdb51

4 files changed

Lines changed: 115 additions & 13 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { PutLifecycleRequest } from '@elastic/elasticsearch/api/types';
9+
10+
export const reportingIlmPolicy: PutLifecycleRequest['body'] = {
11+
policy: {
12+
phases: {
13+
hot: {
14+
actions: {},
15+
},
16+
},
17+
},
18+
};

x-pack/plugins/reporting/server/lib/store/store.test.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
import type { DeeplyMockedKeys } from '@kbn/utility-types/jest';
99
import { ElasticsearchClient } from 'src/core/server';
10-
import { ReportingCore } from '../..';
10+
import { elasticsearchServiceMock } from 'src/core/server/mocks';
11+
import { ReportingCore } from '../../';
1112
import {
1213
createMockConfigSchema,
1314
createMockLevelLogger,
@@ -16,6 +17,8 @@ import {
1617
import { Report } from './report';
1718
import { ReportingStore } from './store';
1819

20+
const { createApiResponse } = elasticsearchServiceMock;
21+
1922
describe('ReportingStore', () => {
2023
const mockLogger = createMockLevelLogger();
2124
let mockCore: ReportingCore;
@@ -339,4 +342,40 @@ describe('ReportingStore', () => {
339342
]
340343
`);
341344
});
345+
346+
describe('start', () => {
347+
it('creates an ILM policy for managing reporting indices if there is not already one', async () => {
348+
mockEsClient.ilm.getLifecycle.mockRejectedValueOnce(createApiResponse({ statusCode: 404 }));
349+
mockEsClient.ilm.putLifecycle.mockResolvedValueOnce(createApiResponse());
350+
351+
const store = new ReportingStore(mockCore, mockLogger);
352+
await store.start();
353+
354+
expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ policy: 'kibana-reporting' });
355+
expect(mockEsClient.ilm.putLifecycle.mock.calls[0][0]).toMatchInlineSnapshot(`
356+
Object {
357+
"body": Object {
358+
"policy": Object {
359+
"phases": Object {
360+
"hot": Object {
361+
"actions": Object {},
362+
},
363+
},
364+
},
365+
},
366+
"policy": "kibana-reporting",
367+
}
368+
`);
369+
});
370+
371+
it('does not create an ILM policy for managing reporting indices if one already exists', async () => {
372+
mockEsClient.ilm.getLifecycle.mockResolvedValueOnce(createApiResponse());
373+
374+
const store = new ReportingStore(mockCore, mockLogger);
375+
await store.start();
376+
377+
expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ policy: 'kibana-reporting' });
378+
expect(mockEsClient.ilm.putLifecycle).not.toHaveBeenCalled();
379+
});
380+
});
342381
});

x-pack/plugins/reporting/server/lib/store/store.ts

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ReportingCore } from '../../';
1111
import { indexTimestamp } from './index_timestamp';
1212
import { mapping } from './mapping';
1313
import { Report } from './report';
14+
import { reportingIlmPolicy } from './report_ilm_policy';
1415

1516
const checkReportIsEditable = (report: Report) => {
1617
if (!report._id || !report._index) {
@@ -52,19 +53,22 @@ export class ReportingStore {
5253
return exists;
5354
}
5455

55-
const indexSettings = {
56-
number_of_shards: 1,
57-
auto_expand_replicas: '0-1',
58-
};
59-
const body = {
60-
settings: indexSettings,
61-
mappings: {
62-
properties: mapping,
63-
},
64-
};
65-
6656
try {
67-
await client.indices.create({ index: indexName, body });
57+
await client.indices.create({
58+
index: indexName,
59+
body: {
60+
settings: {
61+
number_of_shards: 1,
62+
auto_expand_replicas: '0-1',
63+
lifecycle: {
64+
name: this.ilmPolicyName,
65+
},
66+
},
67+
mappings: {
68+
properties: mapping,
69+
},
70+
},
71+
});
6872

6973
return true;
7074
} catch (error) {
@@ -111,6 +115,44 @@ export class ReportingStore {
111115
return client.indices.refresh({ index });
112116
}
113117

118+
private readonly ilmPolicyName = 'kibana-reporting';
119+
120+
private async doesIlmPolicyExist(): Promise<boolean> {
121+
const client = await this.getClient();
122+
try {
123+
await client.ilm.getLifecycle({ policy: this.ilmPolicyName });
124+
return true;
125+
} catch (e) {
126+
if (e.statusCode === 404) {
127+
return false;
128+
}
129+
throw e;
130+
}
131+
}
132+
133+
/**
134+
* Function to be called during plugin start phase. This ensures the environment is correctly
135+
* configured for storage of reports.
136+
*/
137+
public async start() {
138+
const client = await this.getClient();
139+
try {
140+
if (await this.doesIlmPolicyExist()) {
141+
this.logger.debug(`Found ILM policy ${this.ilmPolicyName}; skipping creation.`);
142+
return;
143+
}
144+
this.logger.info(`Creating ILM policy for managing reporting indices: ${this.ilmPolicyName}`);
145+
await client.ilm.putLifecycle({
146+
policy: this.ilmPolicyName,
147+
body: reportingIlmPolicy,
148+
});
149+
} catch (e) {
150+
this.logger.error('Error in start phase');
151+
this.logger.error(e.body.error);
152+
throw e;
153+
}
154+
}
155+
114156
public async addReport(report: Report): Promise<Report> {
115157
let index = report._index;
116158
if (!index) {

x-pack/plugins/reporting/server/plugin.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ export class ReportingPlugin
112112
logger: this.logger,
113113
});
114114

115+
// Note: this must be called after ReportingCore.pluginStart
116+
await store.start();
117+
115118
this.logger.debug('Start complete');
116119
})().catch((e) => {
117120
this.logger.error(`Error in Reporting start, reporting may not function properly`);

0 commit comments

Comments
 (0)