[8.x] [Fleet] Trigger a rollover on error when updating enabled mappings (#205532) (#205637)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Fleet] Trigger a rollover on error when updating enabled mappings
(#205532)](https://github.com/elastic/kibana/pull/205532)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Nicolas
Chaulet","email":"nicolas.chaulet@elastic.co"},"sourceCommit":{"committedDate":"2025-01-06T17:35:34Z","message":"[Fleet]
Trigger a rollover on error when updating enabled mappings
(#205532)","sha":"3d6711bb95ea9eff757097f808a917426abf187f","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","v9.0.0","backport:prev-major"],"title":"[Fleet]
Trigger a rollover on error when updating enabled
mappings","number":205532,"url":"https://github.com/elastic/kibana/pull/205532","mergeCommit":{"message":"[Fleet]
Trigger a rollover on error when updating enabled mappings
(#205532)","sha":"3d6711bb95ea9eff757097f808a917426abf187f"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/205532","number":205532,"mergeCommit":{"message":"[Fleet]
Trigger a rollover on error when updating enabled mappings
(#205532)","sha":"3d6711bb95ea9eff757097f808a917426abf187f"}}]}]
BACKPORT-->

Co-authored-by: Nicolas Chaulet <nicolas.chaulet@elastic.co>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2025-01-08 03:27:40 +11:00 committed by GitHub
parent f5544fc9ac
commit 8c93503038
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 79 additions and 11 deletions

View file

@ -2126,6 +2126,60 @@ describe('EPM template', () => {
})
);
});
it('should rollover on mapper exception that change enabled object mappings', async () => {
const esClient = elasticsearchServiceMock.createElasticsearchClient();
esClient.indices.getDataStream.mockResponse({
data_streams: [{ name: 'test.prefix1-default' }],
} as any);
esClient.indices.get.mockResponse({
'test.prefix1-default': {
mappings: {},
},
} as any);
esClient.indices.simulateTemplate.mockResponse({
template: {
settings: { index: {} },
mappings: {},
},
} as any);
esClient.indices.putMapping.mockImplementation(() => {
throw new errors.ResponseError({
body: {
error: {
type: 'mapper_exception',
reason: `Mappings update for logs-cisco_ise.log-default failed due to ResponseError: mapper_exception
Root causes:
mapper_exception: the [enabled] parameter can't be updated for the object mapping [cisco_ise.log.cisco_av_pair]`,
},
},
} as any);
});
const logger = loggerMock.create();
await updateCurrentWriteIndices(esClient, logger, [
{
templateName: 'test',
indexTemplate: {
index_patterns: ['test.*-*'],
template: {
settings: { index: {} },
mappings: {},
},
} as any,
},
]);
expect(esClient.transport.request).toHaveBeenCalledWith(
expect.objectContaining({
path: '/test.prefix1-default/_rollover',
querystring: {
lazy: true,
},
})
);
});
it('should skip rollover on expected error when flag is on', async () => {
const esClient = elasticsearchServiceMock.createElasticsearchClient();
esClient.indices.getDataStream.mockResponse({

View file

@ -949,6 +949,30 @@ const getDataStreams = async (
}));
};
const MAPPER_EXCEPTION_REASONS_REQUIRING_ROLLOVER = [
'subobjects',
"[enabled] parameter can't be updated for the object mapping",
];
function errorNeedRollover(err: any) {
if (
isResponseError(err) &&
err.statusCode === 400 &&
err.body?.error?.type === 'illegal_argument_exception'
) {
return true;
}
if (
err.body?.error?.type === 'mapper_exception' &&
err.body?.error?.reason &&
MAPPER_EXCEPTION_REASONS_REQUIRING_ROLLOVER.some((reason) =>
err.body?.error?.reason?.includes(reason)
)
) {
return true;
}
}
const rolloverDataStream = (dataStreamName: string, esClient: ElasticsearchClient) => {
try {
// Do no wrap rollovers in retryTransientEsErrors since it is not idempotent
@ -1069,17 +1093,7 @@ const updateExistingDataStream = async ({
// if update fails, rollover data stream and bail out
} catch (err) {
subobjectsFieldChanged =
subobjectsFieldChanged ||
(err.body?.error?.type === 'mapper_exception' &&
err.body?.error?.reason?.includes('subobjects'));
if (
(isResponseError(err) &&
err.statusCode === 400 &&
err.body?.error?.type === 'illegal_argument_exception') ||
// handling the case when subobjects field changed, it should also trigger a rollover
subobjectsFieldChanged
) {
if (errorNeedRollover(err) || subobjectsFieldChanged) {
logger.info(`Mappings update for ${dataStreamName} failed due to ${err}`);
logger.trace(`Attempted mappings: ${mappings}`);
if (options?.skipDataStreamRollover === true) {