Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,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
Expand Down Expand Up @@ -1092,17 +1116,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) {
Expand Down
Loading