[Fleet] cleanup old file upload index and index template (#162329)

This commit is contained in:
Nicolas Chaulet 2023-07-24 09:00:39 -04:00 committed by GitHub
parent 6775f5818e
commit d2825d92bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 174 additions and 1 deletions

View file

@ -29,7 +29,6 @@ jest.mock('./setup/upgrade_package_install_version');
jest.mock('./epm/elasticsearch/template/install', () => {
return {
...jest.requireActual('./epm/elasticsearch/template/install'),
ensureFileUploadWriteIndices: jest.fn(),
};
});

View file

@ -53,6 +53,7 @@ import {
ensurePreconfiguredFleetServerHosts,
getPreconfiguredFleetServerHostFromConfig,
} from './preconfiguration/fleet_server_host';
import { cleanUpOldFileIndices } from './setup/clean_old_fleet_indices';
export interface SetupStatus {
isInitialized: boolean;
@ -75,6 +76,8 @@ async function createSetupSideEffects(
const logger = appContextService.getLogger();
logger.info('Beginning fleet setup');
await cleanUpOldFileIndices(esClient, logger);
await ensureFleetDirectories();
const { agentPolicies: policiesOrUndefined, packages: packagesOrUndefined } =

View file

@ -0,0 +1,104 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks';
import { loggingSystemMock } from '@kbn/core-logging-server-mocks';
import { cleanUpOldFileIndices } from './clean_old_fleet_indices';
describe('cleanUpOldFileIndices', () => {
it('should clean old indices and old index templates', async () => {
const logger = loggingSystemMock.createLogger();
const esClient = elasticsearchServiceMock.createInternalClient();
esClient.indices.get.mockResolvedValueOnce({
'.fleet-files-agent': {},
'.fleet-files-test': {},
});
esClient.indices.get.mockImplementation(({ index }) => {
if (index === '.fleet-files-agent') {
return {
'.fleet-files-agent': {},
'.fleet-files-test': {},
} as any;
}
return {};
});
await cleanUpOldFileIndices(esClient, logger);
expect(esClient.indices.delete).toBeCalledTimes(1);
expect(esClient.indices.delete).toBeCalledWith(
expect.objectContaining({
index: '.fleet-files-agent,.fleet-files-test',
})
);
expect(esClient.indices.deleteIndexTemplate).toBeCalledTimes(1);
expect(esClient.indices.deleteIndexTemplate).toBeCalledWith(
expect.objectContaining({
name: '.fleet-files,.fleet-file-data,.fleet-filedelivery-data,.fleet-filedelivery-meta',
})
);
expect(logger.warn).not.toBeCalled();
});
it('should log a warning and not throw if an unexpected error happen', async () => {
const logger = loggingSystemMock.createLogger();
const esClient = elasticsearchServiceMock.createInternalClient();
esClient.indices.get.mockRejectedValue(new Error('test error'));
await cleanUpOldFileIndices(esClient, logger);
expect(logger.warn).toBeCalledWith('Old fleet indices cleanup failed: test error');
});
it('should handle 404 while deleting index template', async () => {
const logger = loggingSystemMock.createLogger();
const esClient = elasticsearchServiceMock.createInternalClient();
esClient.indices.get.mockResolvedValue({});
esClient.indices.deleteIndexTemplate.mockRejectedValue({
meta: {
statusCode: 404,
},
});
await cleanUpOldFileIndices(esClient, logger);
expect(esClient.indices.deleteIndexTemplate).toBeCalledTimes(1);
expect(logger.warn).not.toBeCalled();
});
it('should handle 404 when deleting old index', async () => {
const logger = loggingSystemMock.createLogger();
const esClient = elasticsearchServiceMock.createInternalClient();
esClient.indices.get.mockResolvedValueOnce({
'.fleet-files-agent': {},
'.fleet-files-test': {},
});
esClient.indices.get.mockImplementation(({ index }) => {
if (index === '.fleet-files-agent') {
return {
'.fleet-files-agent': {},
'.fleet-files-test': {},
} as any;
}
return {};
});
esClient.indices.delete.mockRejectedValue({
meta: {
statusCode: 404,
},
});
await cleanUpOldFileIndices(esClient, logger);
expect(esClient.indices.delete).toBeCalledTimes(1);
expect(logger.warn).not.toBeCalled();
});
});

View file

@ -0,0 +1,67 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import pMap from 'p-map';
const INDICES_TO_CLEAN = [
'.fleet-files-*',
'.fleet-file-data-*',
'.fleet-filedelivery-data-*',
'.fleet-filedelivery-meta-*',
];
const INDEX_TEMPLATE_TO_CLEAN = [
'.fleet-files',
'.fleet-file-data',
'.fleet-filedelivery-data',
'.fleet-filedelivery-meta',
];
/**
* In 8.10 upload feature moved from using index to datastreams, this function allows to clean those old indices.
*/
export async function cleanUpOldFileIndices(esClient: ElasticsearchClient, logger: Logger) {
try {
// Clean indices
await pMap(
INDICES_TO_CLEAN,
async (indiceToClean) => {
const res = await esClient.indices.get({
index: indiceToClean,
});
const indices = Object.keys(res);
if (indices.length) {
await esClient.indices
.delete({
index: indices.join(','),
})
.catch((err) => {
// Skip not found errors
if (err.meta?.statusCode !== 404) {
throw err;
}
});
}
},
{ concurrency: 2 }
);
await esClient.indices
.deleteIndexTemplate({
name: INDEX_TEMPLATE_TO_CLEAN.join(','),
})
.catch((err) => {
// Skip not found errors
if (err.meta?.statusCode !== 404) {
throw err;
}
});
// Clean index template
} catch (err) {
logger.warn(`Old fleet indices cleanup failed: ${err.message}`);
}
}