[Event Log][8.0] Set all event log index assets to hidden (#110929)
* Setting event log indices to hidden * Cleaning up cluster client and adding unit tests * Unit tests * Unit tests * Unit tests * Unit tests * PR feedback Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
7ae423c5bb
commit
604a745de0
|
@ -17,6 +17,12 @@ const createClusterClientMock = () => {
|
|||
createIndexTemplate: jest.fn(),
|
||||
doesAliasExist: jest.fn(),
|
||||
createIndex: jest.fn(),
|
||||
getExistingLegacyIndexTemplates: jest.fn(),
|
||||
setLegacyIndexTemplateToHidden: jest.fn(),
|
||||
getExistingIndices: jest.fn(),
|
||||
setIndexToHidden: jest.fn(),
|
||||
getExistingIndexAliases: jest.fn(),
|
||||
setIndexAliasToHidden: jest.fn(),
|
||||
queryEventsBySavedObjects: jest.fn(),
|
||||
shutdown: jest.fn(),
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ import { findOptionsSchema } from '../event_log_client';
|
|||
import { delay } from '../lib/delay';
|
||||
import { times } from 'lodash';
|
||||
import { DeeplyMockedKeys } from '@kbn/utility-types/jest';
|
||||
import { RequestEvent } from '@elastic/elasticsearch';
|
||||
import { estypes, RequestEvent } from '@elastic/elasticsearch';
|
||||
|
||||
type MockedLogger = ReturnType<typeof loggingSystemMock['createLogger']>;
|
||||
|
||||
|
@ -215,22 +215,39 @@ describe('doesIndexTemplateExist', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('should return true when call cluster returns true', async () => {
|
||||
test('should return true when call cluster to legacy template API returns true', async () => {
|
||||
clusterClient.indices.existsTemplate.mockResolvedValue(asApiResponse(true));
|
||||
clusterClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(false));
|
||||
await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(true);
|
||||
});
|
||||
|
||||
test('should return false when call cluster returns false', async () => {
|
||||
test('should return true when call cluster to index template API returns true', async () => {
|
||||
clusterClient.indices.existsTemplate.mockResolvedValue(asApiResponse(false));
|
||||
clusterClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(true));
|
||||
await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(true);
|
||||
});
|
||||
|
||||
test('should return false when both call cluster calls returns false', async () => {
|
||||
clusterClient.indices.existsTemplate.mockResolvedValue(asApiResponse(false));
|
||||
clusterClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(false));
|
||||
await expect(clusterClientAdapter.doesIndexTemplateExist('foo')).resolves.toEqual(false);
|
||||
});
|
||||
|
||||
test('should throw error when call cluster throws an error', async () => {
|
||||
test('should throw error when call cluster to legacy template API throws an error', async () => {
|
||||
clusterClient.indices.existsTemplate.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.doesIndexTemplateExist('foo')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error checking existance of index template: Fail"`
|
||||
`"error checking existence of index template: Fail"`
|
||||
);
|
||||
});
|
||||
|
||||
test('should throw error when call cluster to index template API throws an error', async () => {
|
||||
clusterClient.indices.existsIndexTemplate.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.doesIndexTemplateExist('foo')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error checking existence of index template: Fail"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -238,7 +255,7 @@ describe('doesIndexTemplateExist', () => {
|
|||
describe('createIndexTemplate', () => {
|
||||
test('should call cluster with given template', async () => {
|
||||
await clusterClientAdapter.createIndexTemplate('foo', { args: true });
|
||||
expect(clusterClient.indices.putTemplate).toHaveBeenCalledWith({
|
||||
expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({
|
||||
name: 'foo',
|
||||
create: true,
|
||||
body: { args: true },
|
||||
|
@ -246,20 +263,274 @@ describe('createIndexTemplate', () => {
|
|||
});
|
||||
|
||||
test(`should throw error if index template still doesn't exist after error is thrown`, async () => {
|
||||
clusterClient.indices.putTemplate.mockRejectedValueOnce(new Error('Fail'));
|
||||
clusterClient.indices.putIndexTemplate.mockRejectedValueOnce(new Error('Fail'));
|
||||
clusterClient.indices.existsTemplate.mockResolvedValueOnce(asApiResponse(false));
|
||||
clusterClient.indices.existsIndexTemplate.mockResolvedValueOnce(asApiResponse(false));
|
||||
await expect(
|
||||
clusterClientAdapter.createIndexTemplate('foo', { args: true })
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`"error creating index template: Fail"`);
|
||||
});
|
||||
|
||||
test('should not throw error if index template exists after error is thrown', async () => {
|
||||
clusterClient.indices.putTemplate.mockRejectedValueOnce(new Error('Fail'));
|
||||
clusterClient.indices.putIndexTemplate.mockRejectedValueOnce(new Error('Fail'));
|
||||
clusterClient.indices.existsTemplate.mockResolvedValueOnce(asApiResponse(true));
|
||||
await clusterClientAdapter.createIndexTemplate('foo', { args: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('getExistingLegacyIndexTemplates', () => {
|
||||
test('should call cluster with given index template pattern', async () => {
|
||||
await clusterClientAdapter.getExistingLegacyIndexTemplates('foo*');
|
||||
expect(clusterClient.indices.getTemplate).toHaveBeenCalledWith(
|
||||
{
|
||||
name: 'foo*',
|
||||
},
|
||||
{ ignore: [404] }
|
||||
);
|
||||
});
|
||||
|
||||
test('should return templates when found', async () => {
|
||||
const response = {
|
||||
'foo-bar-template': {
|
||||
order: 0,
|
||||
index_patterns: ['foo-bar-*'],
|
||||
settings: { index: { number_of_shards: '1' } },
|
||||
mappings: { dynamic: false, properties: {} },
|
||||
aliases: {},
|
||||
},
|
||||
};
|
||||
clusterClient.indices.getTemplate.mockResolvedValue(
|
||||
asApiResponse<estypes.IndicesGetTemplateResponse>(response)
|
||||
);
|
||||
await expect(clusterClientAdapter.getExistingLegacyIndexTemplates('foo*')).resolves.toEqual(
|
||||
response
|
||||
);
|
||||
});
|
||||
|
||||
test('should throw error when call cluster throws an error', async () => {
|
||||
clusterClient.indices.getTemplate.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.getExistingLegacyIndexTemplates('foo*')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error getting existing legacy index templates: Fail"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setLegacyIndexTemplateToHidden', () => {
|
||||
test('should call cluster with given index template name and template', async () => {
|
||||
const currentTemplate = {
|
||||
order: 0,
|
||||
index_patterns: ['foo-bar-*'],
|
||||
settings: { index: { number_of_shards: '1' } },
|
||||
mappings: { dynamic: false, properties: {} },
|
||||
aliases: {},
|
||||
};
|
||||
await clusterClientAdapter.setLegacyIndexTemplateToHidden('foo-bar-template', currentTemplate);
|
||||
expect(clusterClient.indices.putTemplate).toHaveBeenCalledWith({
|
||||
name: 'foo-bar-template',
|
||||
body: {
|
||||
order: 0,
|
||||
index_patterns: ['foo-bar-*'],
|
||||
settings: { index: { number_of_shards: '1' }, 'index.hidden': true },
|
||||
mappings: { dynamic: false, properties: {} },
|
||||
aliases: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should throw error when call cluster throws an error', async () => {
|
||||
clusterClient.indices.putTemplate.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.setLegacyIndexTemplateToHidden('foo-bar-template', {
|
||||
aliases: {},
|
||||
index_patterns: [],
|
||||
mappings: {},
|
||||
order: 0,
|
||||
settings: {},
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error setting existing legacy index template foo-bar-template to hidden: Fail"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getExistingIndices', () => {
|
||||
test('should call cluster with given index pattern', async () => {
|
||||
await clusterClientAdapter.getExistingIndices('foo*');
|
||||
expect(clusterClient.indices.getSettings).toHaveBeenCalledWith(
|
||||
{
|
||||
index: 'foo*',
|
||||
},
|
||||
{ ignore: [404] }
|
||||
);
|
||||
});
|
||||
|
||||
test('should return indices when found', async () => {
|
||||
const response = {
|
||||
'foo-bar-000001': {
|
||||
settings: {
|
||||
index: {
|
||||
number_of_shards: 1,
|
||||
uuid: 'Ure4d9edQbCMtcmyy0ObrA',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
clusterClient.indices.getSettings.mockResolvedValue(
|
||||
asApiResponse<estypes.IndicesGetSettingsResponse>(response)
|
||||
);
|
||||
await expect(clusterClientAdapter.getExistingIndices('foo*')).resolves.toEqual(response);
|
||||
});
|
||||
|
||||
test('should throw error when call cluster throws an error', async () => {
|
||||
clusterClient.indices.getSettings.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.getExistingIndices('foo*')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error getting existing indices matching pattern foo*: Fail"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setIndexToHidden', () => {
|
||||
test('should call cluster with given index name', async () => {
|
||||
await clusterClientAdapter.setIndexToHidden('foo-bar-000001');
|
||||
expect(clusterClient.indices.putSettings).toHaveBeenCalledWith({
|
||||
index: 'foo-bar-000001',
|
||||
body: {
|
||||
settings: {
|
||||
'index.hidden': true,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should throw error when call cluster throws an error', async () => {
|
||||
clusterClient.indices.putSettings.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.setIndexToHidden('foo-bar-000001')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error setting existing index foo-bar-000001 to hidden: Fail"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getExistingIndexAliases', () => {
|
||||
test('should call cluster with given index pattern', async () => {
|
||||
await clusterClientAdapter.getExistingIndexAliases('foo*');
|
||||
expect(clusterClient.indices.getAlias).toHaveBeenCalledWith(
|
||||
{
|
||||
index: 'foo*',
|
||||
},
|
||||
{ ignore: [404] }
|
||||
);
|
||||
});
|
||||
|
||||
test('should return aliases when found', async () => {
|
||||
const response = {
|
||||
'foo-bar-000001': {
|
||||
aliases: {
|
||||
'foo-bar': {
|
||||
is_write_index: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
clusterClient.indices.getAlias.mockResolvedValue(
|
||||
asApiResponse<estypes.IndicesGetAliasResponse>(response)
|
||||
);
|
||||
await expect(clusterClientAdapter.getExistingIndexAliases('foo*')).resolves.toEqual(response);
|
||||
});
|
||||
|
||||
test('should throw error when call cluster throws an error', async () => {
|
||||
clusterClient.indices.getAlias.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.getExistingIndexAliases('foo*')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error getting existing index aliases matching pattern foo*: Fail"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setIndexAliasToHidden', () => {
|
||||
test('should call cluster with given index name and aliases', async () => {
|
||||
await clusterClientAdapter.setIndexAliasToHidden('foo-bar-000001', {
|
||||
aliases: {
|
||||
'foo-bar': {
|
||||
is_write_index: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(clusterClient.indices.updateAliases).toHaveBeenCalledWith({
|
||||
body: {
|
||||
actions: [
|
||||
{
|
||||
add: {
|
||||
index: 'foo-bar-000001',
|
||||
alias: 'foo-bar',
|
||||
is_hidden: true,
|
||||
is_write_index: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should update multiple aliases at once and preserve existing alias settings', async () => {
|
||||
await clusterClientAdapter.setIndexAliasToHidden('foo-bar-000001', {
|
||||
aliases: {
|
||||
'foo-bar': {
|
||||
is_write_index: true,
|
||||
},
|
||||
'foo-b': {
|
||||
index_routing: 'index',
|
||||
routing: 'route',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(clusterClient.indices.updateAliases).toHaveBeenCalledWith({
|
||||
body: {
|
||||
actions: [
|
||||
{
|
||||
add: {
|
||||
index: 'foo-bar-000001',
|
||||
alias: 'foo-bar',
|
||||
is_hidden: true,
|
||||
is_write_index: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
add: {
|
||||
index: 'foo-bar-000001',
|
||||
alias: 'foo-b',
|
||||
is_hidden: true,
|
||||
index_routing: 'index',
|
||||
routing: 'route',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should throw error when call cluster throws an error', async () => {
|
||||
clusterClient.indices.updateAliases.mockRejectedValue(new Error('Fail'));
|
||||
await expect(
|
||||
clusterClientAdapter.setIndexAliasToHidden('foo-bar-000001', {
|
||||
aliases: {
|
||||
'foo-bar': {
|
||||
is_write_index: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"error setting existing index aliases for index foo-bar-000001 to is_hidden: Fail"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('doesAliasExist', () => {
|
||||
test('should call cluster with proper arguments', async () => {
|
||||
await clusterClientAdapter.doesAliasExist('foo');
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { Subject } from 'rxjs';
|
||||
import { bufferTime, filter as rxFilter, switchMap } from 'rxjs/operators';
|
||||
import { reject, isUndefined, isNumber } from 'lodash';
|
||||
import { reject, isUndefined, isNumber, pick } from 'lodash';
|
||||
import type { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import { Logger, ElasticsearchClient } from 'src/core/server';
|
||||
import util from 'util';
|
||||
|
@ -163,17 +163,23 @@ export class ClusterClientAdapter<TDoc extends { body: AliasAny; index: string }
|
|||
public async doesIndexTemplateExist(name: string): Promise<boolean> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
const { body } = await esClient.indices.existsTemplate({ name });
|
||||
return body as boolean;
|
||||
const { body: legacyResult } = await esClient.indices.existsTemplate({ name });
|
||||
const { body: indexTemplateResult } = await esClient.indices.existsIndexTemplate({ name });
|
||||
return (legacyResult as boolean) || (indexTemplateResult as boolean);
|
||||
} catch (err) {
|
||||
throw new Error(`error checking existance of index template: ${err.message}`);
|
||||
throw new Error(`error checking existence of index template: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async createIndexTemplate(name: string, template: Record<string, unknown>): Promise<void> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
await esClient.indices.putTemplate({ name, body: template, create: true });
|
||||
await esClient.indices.putIndexTemplate({
|
||||
name,
|
||||
body: template,
|
||||
// @ts-expect-error doesn't exist in @elastic/elasticsearch
|
||||
create: true,
|
||||
});
|
||||
} catch (err) {
|
||||
// The error message doesn't have a type attribute we can look to guarantee it's due
|
||||
// to the template already existing (only long message) so we'll check ourselves to see
|
||||
|
@ -188,6 +194,128 @@ export class ClusterClientAdapter<TDoc extends { body: AliasAny; index: string }
|
|||
}
|
||||
}
|
||||
|
||||
public async getExistingLegacyIndexTemplates(
|
||||
indexTemplatePattern: string
|
||||
): Promise<estypes.IndicesGetTemplateResponse> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
const { body: templates } = await esClient.indices.getTemplate(
|
||||
{ name: indexTemplatePattern },
|
||||
{ ignore: [404] }
|
||||
);
|
||||
return templates;
|
||||
} catch (err) {
|
||||
throw new Error(`error getting existing legacy index templates: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async setLegacyIndexTemplateToHidden(
|
||||
indexTemplateName: string,
|
||||
currentIndexTemplate: estypes.IndicesTemplateMapping
|
||||
): Promise<void> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
await esClient.indices.putTemplate({
|
||||
name: indexTemplateName,
|
||||
body: {
|
||||
...currentIndexTemplate,
|
||||
settings: {
|
||||
...currentIndexTemplate.settings,
|
||||
'index.hidden': true,
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`error setting existing legacy index template ${indexTemplateName} to hidden: ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async getExistingIndices(
|
||||
indexPattern: string
|
||||
): Promise<estypes.IndicesGetSettingsResponse> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
const { body: indexSettings } = await esClient.indices.getSettings(
|
||||
{ index: indexPattern },
|
||||
{ ignore: [404] }
|
||||
);
|
||||
return indexSettings;
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`error getting existing indices matching pattern ${indexPattern}: ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async setIndexToHidden(indexName: string): Promise<void> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
await esClient.indices.putSettings({
|
||||
index: indexName,
|
||||
body: {
|
||||
settings: {
|
||||
'index.hidden': true,
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error(`error setting existing index ${indexName} to hidden: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async getExistingIndexAliases(
|
||||
indexPattern: string
|
||||
): Promise<estypes.IndicesGetAliasResponse> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
const { body: indexAliases } = await esClient.indices.getAlias(
|
||||
{ index: indexPattern },
|
||||
{ ignore: [404] }
|
||||
);
|
||||
return indexAliases;
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`error getting existing index aliases matching pattern ${indexPattern}: ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async setIndexAliasToHidden(
|
||||
indexName: string,
|
||||
currentAliases: estypes.IndicesGetAliasIndexAliases
|
||||
): Promise<void> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
await esClient.indices.updateAliases({
|
||||
body: {
|
||||
actions: Object.keys(currentAliases.aliases).map((aliasName) => {
|
||||
const existingAliasOptions = pick(currentAliases.aliases[aliasName], [
|
||||
'is_write_index',
|
||||
'filter',
|
||||
'index_routing',
|
||||
'routing',
|
||||
'search_routing',
|
||||
]);
|
||||
return {
|
||||
add: {
|
||||
...existingAliasOptions,
|
||||
index: indexName,
|
||||
alias: aliasName,
|
||||
is_hidden: true,
|
||||
},
|
||||
};
|
||||
}),
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`error setting existing index aliases for index ${indexName} to is_hidden: ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async doesAliasExist(name: string): Promise<boolean> {
|
||||
try {
|
||||
const esClient = await this.elasticsearchClientPromise;
|
||||
|
|
|
@ -64,6 +64,7 @@ describe('createEsContext', () => {
|
|||
elasticsearchClientPromise: Promise.resolve(elasticsearchClient),
|
||||
});
|
||||
elasticsearchClient.indices.existsTemplate.mockResolvedValue(asApiResponse(false));
|
||||
elasticsearchClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(false));
|
||||
elasticsearchClient.indices.existsAlias.mockResolvedValue(asApiResponse(false));
|
||||
const doesAliasExist = await context.esAdapter.doesAliasExist(context.esNames.alias);
|
||||
expect(doesAliasExist).toBeFalsy();
|
||||
|
|
|
@ -25,10 +25,11 @@ describe('getIndexTemplate()', () => {
|
|||
test('returns the correct details of the index template', () => {
|
||||
const indexTemplate = getIndexTemplate(esNames);
|
||||
expect(indexTemplate.index_patterns).toEqual([esNames.indexPatternWithVersion]);
|
||||
expect(indexTemplate.settings.number_of_shards).toBeGreaterThanOrEqual(0);
|
||||
expect(indexTemplate.settings.auto_expand_replicas).toBe('0-1');
|
||||
expect(indexTemplate.settings['index.lifecycle.name']).toBe(esNames.ilmPolicy);
|
||||
expect(indexTemplate.settings['index.lifecycle.rollover_alias']).toBe(esNames.alias);
|
||||
expect(indexTemplate.mappings).toMatchObject({});
|
||||
expect(indexTemplate.template.settings.number_of_shards).toBeGreaterThanOrEqual(0);
|
||||
expect(indexTemplate.template.settings.auto_expand_replicas).toBe('0-1');
|
||||
expect(indexTemplate.template.settings['index.lifecycle.name']).toBe(esNames.ilmPolicy);
|
||||
expect(indexTemplate.template.settings['index.lifecycle.rollover_alias']).toBe(esNames.alias);
|
||||
expect(indexTemplate.template.settings['index.hidden']).toBe(true);
|
||||
expect(indexTemplate.template.mappings).toMatchObject({});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,13 +12,16 @@ import mappings from '../../generated/mappings.json';
|
|||
export function getIndexTemplate(esNames: EsNames) {
|
||||
const indexTemplateBody = {
|
||||
index_patterns: [esNames.indexPatternWithVersion],
|
||||
settings: {
|
||||
number_of_shards: 1,
|
||||
auto_expand_replicas: '0-1',
|
||||
'index.lifecycle.name': esNames.ilmPolicy,
|
||||
'index.lifecycle.rollover_alias': esNames.alias,
|
||||
template: {
|
||||
settings: {
|
||||
number_of_shards: 1,
|
||||
auto_expand_replicas: '0-1',
|
||||
'index.lifecycle.name': esNames.ilmPolicy,
|
||||
'index.lifecycle.rollover_alias': esNames.alias,
|
||||
'index.hidden': true,
|
||||
},
|
||||
mappings,
|
||||
},
|
||||
mappings,
|
||||
};
|
||||
|
||||
return indexTemplateBody;
|
||||
|
|
|
@ -13,6 +13,327 @@ describe('initializeEs', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
esContext = contextMock.create();
|
||||
esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({});
|
||||
esContext.esAdapter.getExistingIndices.mockResolvedValue({});
|
||||
esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({});
|
||||
});
|
||||
|
||||
test(`should update existing index templates if any exist and are not hidden`, async () => {
|
||||
const testTemplate = {
|
||||
order: 0,
|
||||
index_patterns: ['foo-bar-*'],
|
||||
settings: {
|
||||
index: {
|
||||
lifecycle: {
|
||||
name: 'foo-bar-policy',
|
||||
rollover_alias: 'foo-bar-1',
|
||||
},
|
||||
number_of_shards: '1',
|
||||
auto_expand_replicas: '0-1',
|
||||
},
|
||||
},
|
||||
mappings: {},
|
||||
aliases: {},
|
||||
};
|
||||
esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({
|
||||
'foo-bar-template': testTemplate,
|
||||
});
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).toHaveBeenCalledWith(
|
||||
'foo-bar-template',
|
||||
testTemplate
|
||||
);
|
||||
});
|
||||
|
||||
test(`should not update existing index templates if any exist and are already hidden`, async () => {
|
||||
const testTemplate = {
|
||||
order: 0,
|
||||
index_patterns: ['foo-bar-*'],
|
||||
settings: {
|
||||
index: {
|
||||
lifecycle: {
|
||||
name: 'foo-bar-policy',
|
||||
rollover_alias: 'foo-bar-1',
|
||||
},
|
||||
hidden: 'true',
|
||||
number_of_shards: '1',
|
||||
auto_expand_replicas: '0-1',
|
||||
},
|
||||
},
|
||||
mappings: {},
|
||||
aliases: {},
|
||||
};
|
||||
esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({
|
||||
'foo-bar-template': testTemplate,
|
||||
});
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should continue initialization if getting existing index templates throws an error`, async () => {
|
||||
esContext.esAdapter.getExistingLegacyIndexTemplates.mockRejectedValue(new Error('Fail'));
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled();
|
||||
expect(esContext.logger.error).toHaveBeenCalledWith(
|
||||
`error getting existing index templates - Fail`
|
||||
);
|
||||
expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).not.toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should continue initialization if updating existing index templates throws an error`, async () => {
|
||||
const testTemplate = {
|
||||
order: 0,
|
||||
index_patterns: ['foo-bar-*'],
|
||||
settings: {
|
||||
index: {
|
||||
lifecycle: {
|
||||
name: 'foo-bar-policy',
|
||||
rollover_alias: 'foo-bar-1',
|
||||
},
|
||||
number_of_shards: '1',
|
||||
auto_expand_replicas: '0-1',
|
||||
},
|
||||
},
|
||||
mappings: {},
|
||||
aliases: {},
|
||||
};
|
||||
esContext.esAdapter.getExistingLegacyIndexTemplates.mockResolvedValue({
|
||||
'foo-bar-template': testTemplate,
|
||||
'another-test-template': testTemplate,
|
||||
});
|
||||
esContext.esAdapter.setLegacyIndexTemplateToHidden.mockRejectedValueOnce(new Error('Fail'));
|
||||
esContext.esAdapter.setLegacyIndexTemplateToHidden.mockResolvedValueOnce();
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingLegacyIndexTemplates).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).toHaveBeenCalledWith(
|
||||
'foo-bar-template',
|
||||
testTemplate
|
||||
);
|
||||
expect(esContext.esAdapter.setLegacyIndexTemplateToHidden).toHaveBeenCalledWith(
|
||||
'another-test-template',
|
||||
testTemplate
|
||||
);
|
||||
expect(esContext.logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(esContext.logger.error).toHaveBeenCalledWith(
|
||||
`error setting existing \"foo-bar-template\" index template to hidden - Fail`
|
||||
);
|
||||
expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should update existing index settings if any exist and are not hidden`, async () => {
|
||||
const testSettings = {
|
||||
settings: {
|
||||
index: {
|
||||
lifecycle: {
|
||||
name: 'foo-bar-policy',
|
||||
rollover_alias: 'foo-bar-1',
|
||||
},
|
||||
routing: {
|
||||
allocation: {
|
||||
include: {
|
||||
_tier_preference: 'data_content',
|
||||
},
|
||||
},
|
||||
},
|
||||
number_of_shards: '1',
|
||||
auto_expand_replicas: '0-1',
|
||||
provided_name: '.kibana-event-log-7.15.0-000001',
|
||||
creation_date: '1630439186791',
|
||||
number_of_replicas: '0',
|
||||
uuid: 'Ure4d9edQbCMtcmyy0ObrA',
|
||||
version: {
|
||||
created: '7150099',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
esContext.esAdapter.getExistingIndices.mockResolvedValue({
|
||||
'foo-bar-000001': testSettings,
|
||||
});
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setIndexToHidden).toHaveBeenCalledWith('foo-bar-000001');
|
||||
});
|
||||
|
||||
test(`should not update existing index settings if any exist and are already hidden`, async () => {
|
||||
const testSettings = {
|
||||
settings: {
|
||||
index: {
|
||||
lifecycle: {
|
||||
name: 'foo-bar-policy',
|
||||
rollover_alias: 'foo-bar-1',
|
||||
},
|
||||
routing: {
|
||||
allocation: {
|
||||
include: {
|
||||
_tier_preference: 'data_content',
|
||||
},
|
||||
},
|
||||
},
|
||||
hidden: 'true',
|
||||
number_of_shards: '1',
|
||||
auto_expand_replicas: '0-1',
|
||||
provided_name: '.kibana-event-log-7.15.0-000001',
|
||||
creation_date: '1630439186791',
|
||||
number_of_replicas: '0',
|
||||
uuid: 'Ure4d9edQbCMtcmyy0ObrA',
|
||||
version: {
|
||||
created: '7150099',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
esContext.esAdapter.getExistingIndices.mockResolvedValue({
|
||||
'foo-bar-000001': testSettings,
|
||||
});
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should continue initialization if getting existing index settings throws an error`, async () => {
|
||||
esContext.esAdapter.getExistingIndices.mockRejectedValue(new Error('Fail'));
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled();
|
||||
expect(esContext.logger.error).toHaveBeenCalledWith(`error getting existing indices - Fail`);
|
||||
expect(esContext.esAdapter.setIndexToHidden).not.toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should continue initialization if updating existing index settings throws an error`, async () => {
|
||||
const testSettings = {
|
||||
settings: {
|
||||
index: {
|
||||
lifecycle: {
|
||||
name: 'foo-bar-policy',
|
||||
rollover_alias: 'foo-bar-1',
|
||||
},
|
||||
routing: {
|
||||
allocation: {
|
||||
include: {
|
||||
_tier_preference: 'data_content',
|
||||
},
|
||||
},
|
||||
},
|
||||
number_of_shards: '1',
|
||||
auto_expand_replicas: '0-1',
|
||||
provided_name: '.kibana-event-log-7.15.0-000001',
|
||||
creation_date: '1630439186791',
|
||||
number_of_replicas: '0',
|
||||
uuid: 'Ure4d9edQbCMtcmyy0ObrA',
|
||||
version: {
|
||||
created: '7150099',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
esContext.esAdapter.getExistingIndices.mockResolvedValue({
|
||||
'foo-bar-000001': testSettings,
|
||||
'foo-bar-000002': testSettings,
|
||||
});
|
||||
|
||||
esContext.esAdapter.setIndexToHidden.mockRejectedValueOnce(new Error('Fail'));
|
||||
esContext.esAdapter.setIndexToHidden.mockResolvedValueOnce();
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndices).toHaveBeenCalled();
|
||||
expect(esContext.logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(esContext.logger.error).toHaveBeenCalledWith(
|
||||
`error setting existing \"foo-bar-000001\" index to hidden - Fail`
|
||||
);
|
||||
expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should update existing index aliases if any exist and are not hidden`, async () => {
|
||||
const testAliases = {
|
||||
aliases: {
|
||||
'foo-bar': {
|
||||
is_write_index: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({
|
||||
'foo-bar-000001': testAliases,
|
||||
});
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setIndexAliasToHidden).toHaveBeenCalledWith(
|
||||
'foo-bar-000001',
|
||||
testAliases
|
||||
);
|
||||
});
|
||||
|
||||
test(`should not update existing index aliases if any exist and are already hidden`, async () => {
|
||||
const testAliases = {
|
||||
aliases: {
|
||||
'foo-bar': {
|
||||
is_write_index: true,
|
||||
is_hidden: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({
|
||||
'foo-bar-000001': testAliases,
|
||||
});
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should continue initialization if getting existing index aliases throws an error`, async () => {
|
||||
esContext.esAdapter.getExistingIndexAliases.mockRejectedValue(new Error('Fail'));
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled();
|
||||
expect(esContext.logger.error).toHaveBeenCalledWith(
|
||||
`error getting existing index aliases - Fail`
|
||||
);
|
||||
expect(esContext.esAdapter.setIndexAliasToHidden).not.toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should continue initialization if updating existing index aliases throws an error`, async () => {
|
||||
const testAliases = {
|
||||
aliases: {
|
||||
'foo-bar': {
|
||||
is_write_index: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
esContext.esAdapter.getExistingIndexAliases.mockResolvedValue({
|
||||
'foo-bar-000001': testAliases,
|
||||
'foo-bar-000002': testAliases,
|
||||
});
|
||||
esContext.esAdapter.setIndexAliasToHidden.mockRejectedValueOnce(new Error('Fail'));
|
||||
esContext.esAdapter.setIndexAliasToHidden.mockResolvedValueOnce();
|
||||
|
||||
await initializeEs(esContext);
|
||||
expect(esContext.esAdapter.getExistingIndexAliases).toHaveBeenCalled();
|
||||
expect(esContext.esAdapter.setIndexAliasToHidden).toHaveBeenCalledWith(
|
||||
'foo-bar-000001',
|
||||
testAliases
|
||||
);
|
||||
expect(esContext.esAdapter.setIndexAliasToHidden).toHaveBeenCalledWith(
|
||||
'foo-bar-000002',
|
||||
testAliases
|
||||
);
|
||||
expect(esContext.logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(esContext.logger.error).toHaveBeenCalledWith(
|
||||
`error setting existing \"foo-bar-000001\" index aliases - Fail`
|
||||
);
|
||||
expect(esContext.esAdapter.doesIlmPolicyExist).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`should create ILM policy if it doesn't exist`, async () => {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IndicesAlias, IndicesIndexStatePrefixedSettings } from '@elastic/elasticsearch/api/types';
|
||||
import { estypes } from '@elastic/elasticsearch';
|
||||
import { getIlmPolicy, getIndexTemplate } from './documents';
|
||||
import { EsContext } from './context';
|
||||
|
||||
|
@ -25,6 +27,7 @@ export async function initializeEs(esContext: EsContext): Promise<boolean> {
|
|||
async function initializeEsResources(esContext: EsContext) {
|
||||
const steps = new EsInitializationSteps(esContext);
|
||||
|
||||
await steps.setExistingAssetsToHidden();
|
||||
await steps.createIlmPolicyIfNotExists();
|
||||
await steps.createIndexTemplateIfNotExists();
|
||||
await steps.createInitialIndexIfNotExists();
|
||||
|
@ -35,6 +38,122 @@ class EsInitializationSteps {
|
|||
this.esContext = esContext;
|
||||
}
|
||||
|
||||
async setExistingIndexTemplatesToHidden() {
|
||||
let indexTemplates: estypes.IndicesGetTemplateResponse = {};
|
||||
try {
|
||||
// look up existing index templates and update index.hidden to true if that
|
||||
// setting is currently false or undefined
|
||||
|
||||
// since we are updating to the new index template API and converting new event log
|
||||
// indices to hidden in the same PR, we only need to use the legacy template API to
|
||||
// look for and update existing event log indices.
|
||||
indexTemplates = await this.esContext.esAdapter.getExistingLegacyIndexTemplates(
|
||||
this.esContext.esNames.indexPattern
|
||||
);
|
||||
} catch (err) {
|
||||
// errors when trying to get existing index templates
|
||||
// should not block the rest of initialization, log the error and move on
|
||||
this.esContext.logger.error(`error getting existing index templates - ${err.message}`);
|
||||
}
|
||||
|
||||
Object.keys(indexTemplates).forEach(async (indexTemplateName: string) => {
|
||||
try {
|
||||
const hidden: string | boolean = indexTemplates[indexTemplateName]?.settings?.index?.hidden;
|
||||
// Check to see if this index template is hidden
|
||||
if (hidden !== true && hidden !== 'true') {
|
||||
this.esContext.logger.debug(
|
||||
`setting existing "${indexTemplateName}" index template to hidden.`
|
||||
);
|
||||
|
||||
await this.esContext.esAdapter.setLegacyIndexTemplateToHidden(
|
||||
indexTemplateName,
|
||||
indexTemplates[indexTemplateName]
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
// errors when trying to update existing index templates to hidden
|
||||
// should not block the rest of initialization, log the error and move on
|
||||
this.esContext.logger.error(
|
||||
`error setting existing "${indexTemplateName}" index template to hidden - ${err.message}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async setExistingIndicesToHidden() {
|
||||
let indices: estypes.IndicesGetSettingsResponse = {};
|
||||
try {
|
||||
// look up existing indices and update index.hidden to true if that
|
||||
// setting is currently false or undefined
|
||||
indices = await this.esContext.esAdapter.getExistingIndices(
|
||||
this.esContext.esNames.indexPattern
|
||||
);
|
||||
} catch (err) {
|
||||
// errors when trying to get existing indices
|
||||
// should not block the rest of initialization, log the error and move on
|
||||
this.esContext.logger.error(`error getting existing indices - ${err.message}`);
|
||||
}
|
||||
|
||||
Object.keys(indices).forEach(async (indexName: string) => {
|
||||
try {
|
||||
const hidden: string | boolean | undefined = (indices[indexName]
|
||||
?.settings as IndicesIndexStatePrefixedSettings)?.index?.hidden;
|
||||
|
||||
// Check to see if this index template is hidden
|
||||
if (hidden !== true && hidden !== 'true') {
|
||||
this.esContext.logger.debug(`setting existing ${indexName} index to hidden.`);
|
||||
await this.esContext.esAdapter.setIndexToHidden(indexName);
|
||||
}
|
||||
} catch (err) {
|
||||
// errors when trying to update existing indices to hidden
|
||||
// should not block the rest of initialization, log the error and move on
|
||||
this.esContext.logger.error(
|
||||
`error setting existing "${indexName}" index to hidden - ${err.message}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async setExistingIndexAliasesToHidden() {
|
||||
let indexAliases: estypes.IndicesGetAliasResponse = {};
|
||||
try {
|
||||
// Look up existing index aliases and update index.is_hidden to true if that
|
||||
// setting is currently false or undefined
|
||||
indexAliases = await this.esContext.esAdapter.getExistingIndexAliases(
|
||||
this.esContext.esNames.indexPattern
|
||||
);
|
||||
} catch (err) {
|
||||
// errors when trying to get existing index aliases
|
||||
// should not block the rest of initialization, log the error and move on
|
||||
this.esContext.logger.error(`error getting existing index aliases - ${err.message}`);
|
||||
}
|
||||
Object.keys(indexAliases).forEach(async (indexName: string) => {
|
||||
try {
|
||||
const aliases = indexAliases[indexName]?.aliases;
|
||||
const hasNotHiddenAliases: boolean = Object.keys(aliases).some((alias: string) => {
|
||||
return (aliases[alias] as IndicesAlias)?.is_hidden !== true;
|
||||
});
|
||||
|
||||
if (hasNotHiddenAliases) {
|
||||
this.esContext.logger.debug(`setting existing "${indexName}" index aliases to hidden.`);
|
||||
await this.esContext.esAdapter.setIndexAliasToHidden(indexName, indexAliases[indexName]);
|
||||
}
|
||||
} catch (err) {
|
||||
// errors when trying to set existing index aliases to is_hidden
|
||||
// should not block the rest of initialization, log the error and move on
|
||||
this.esContext.logger.error(
|
||||
`error setting existing "${indexName}" index aliases - ${err.message}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async setExistingAssetsToHidden(): Promise<void> {
|
||||
await this.setExistingIndexTemplatesToHidden();
|
||||
await this.setExistingIndicesToHidden();
|
||||
await this.setExistingIndexAliasesToHidden();
|
||||
}
|
||||
|
||||
async createIlmPolicyIfNotExists(): Promise<void> {
|
||||
const exists = await this.esContext.esAdapter.doesIlmPolicyExist(
|
||||
this.esContext.esNames.ilmPolicy
|
||||
|
@ -67,6 +186,7 @@ class EsInitializationSteps {
|
|||
aliases: {
|
||||
[this.esContext.esNames.alias]: {
|
||||
is_write_index: true,
|
||||
is_hidden: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue