mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[Fleet] Enable rollover in custom integrations install when getting mapper_exception error (#186991)
Fixes https://github.com/elastic/kibana/issues/183496
Fixes https://github.com/elastic/kibana/issues/180062
## Summary
Custom integration creation / integration update currently fails on
changing subobjects property on mapping with `mapper_exception` error.
This PR handles this case by triggering a rollover when the error is
received.
## Testing
- In dev tools, enter the following
```
POST logs-testintegration.test-default/_doc
{
"message": "abc"
}
```
- Navigate to `/app/observabilityOnboarding/customLogs/?category=logs` and fill it with the following:

In the screenshot the error is visible but in the current branch the request should succeed and install `testintegration` correctly.
### Checklist
- [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios
---------
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
003ff3e601
commit
2b611d8835
3 changed files with 117 additions and 13 deletions
|
@ -1805,6 +1805,59 @@ describe('EPM template', () => {
|
|||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should rollover on expected error when field subobjects in mappings changed', 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: { subobjects: false },
|
||||
},
|
||||
} as any);
|
||||
esClient.indices.putMapping.mockImplementation(() => {
|
||||
throw new errors.ResponseError({
|
||||
body: {
|
||||
error: {
|
||||
message:
|
||||
'mapper_exception\n' +
|
||||
'\tRoot causes:\n' +
|
||||
"\t\tmapper_exception: the [subobjects] parameter can't be updated for the object mapping [_doc]",
|
||||
},
|
||||
},
|
||||
} 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({
|
||||
|
|
|
@ -1012,7 +1012,6 @@ const updateExistingDataStream = async ({
|
|||
|
||||
const existingDsConfig = Object.values(existingDs);
|
||||
const currentBackingIndexConfig = existingDsConfig.at(-1);
|
||||
|
||||
const currentIndexMode = currentBackingIndexConfig?.settings?.index?.mode;
|
||||
// @ts-expect-error Property 'mode' does not exist on type 'MappingSourceField'
|
||||
const currentSourceType = currentBackingIndexConfig.mappings?._source?.mode;
|
||||
|
@ -1020,7 +1019,7 @@ const updateExistingDataStream = async ({
|
|||
let settings: IndicesIndexSettings;
|
||||
let mappings: MappingTypeMapping;
|
||||
let lifecycle: any;
|
||||
|
||||
let subobjectsFieldChanged: boolean = false;
|
||||
try {
|
||||
const simulateResult = await retryTransientEsErrors(async () =>
|
||||
esClient.indices.simulateTemplate({
|
||||
|
@ -1040,7 +1039,9 @@ const updateExistingDataStream = async ({
|
|||
delete mappings.properties.stream;
|
||||
delete mappings.properties.data_stream;
|
||||
}
|
||||
|
||||
if (currentBackingIndexConfig?.mappings?.subobjects !== mappings.subobjects) {
|
||||
subobjectsFieldChanged = true;
|
||||
}
|
||||
logger.info(`Attempt to update the mappings for the ${dataStreamName} (write_index_only)`);
|
||||
await retryTransientEsErrors(
|
||||
() =>
|
||||
|
@ -1055,9 +1056,11 @@ const updateExistingDataStream = async ({
|
|||
// if update fails, rollover data stream and bail out
|
||||
} catch (err) {
|
||||
if (
|
||||
isResponseError(err) &&
|
||||
err.statusCode === 400 &&
|
||||
err.body?.error?.type === 'illegal_argument_exception'
|
||||
(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
|
||||
) {
|
||||
logger.info(`Mappings update for ${dataStreamName} failed due to ${err}`);
|
||||
if (options?.skipDataStreamRollover === true) {
|
||||
|
|
|
@ -26,13 +26,12 @@ export default function (providerContext: FtrProviderContext) {
|
|||
.send({ force: true });
|
||||
};
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/180062
|
||||
describe.skip('Installing custom integrations', async () => {
|
||||
describe('TESTME Installing custom integrations', async () => {
|
||||
afterEach(async () => {
|
||||
await uninstallPackage();
|
||||
});
|
||||
|
||||
it("Correcty installs a custom integration and all of it's assets", async () => {
|
||||
it('Correcty installs a custom integration and all of its assets', async () => {
|
||||
const response = await supertest
|
||||
.post(`/api/fleet/epm/custom_integrations`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
|
@ -170,20 +169,40 @@ export default function (providerContext: FtrProviderContext) {
|
|||
dynamic_templates: [
|
||||
{
|
||||
ecs_timestamp: {
|
||||
match: '@timestamp',
|
||||
mapping: {
|
||||
ignore_malformed: false,
|
||||
type: 'date',
|
||||
},
|
||||
match: '@timestamp',
|
||||
},
|
||||
},
|
||||
{
|
||||
ecs_message_match_only_text: {
|
||||
path_match: ['message', '*.message'],
|
||||
unmatch_mapping_type: 'object',
|
||||
mapping: {
|
||||
type: 'match_only_text',
|
||||
},
|
||||
path_match: ['message', '*.message'],
|
||||
unmatch_mapping_type: 'object',
|
||||
},
|
||||
},
|
||||
{
|
||||
ecs_non_indexed_keyword: {
|
||||
mapping: {
|
||||
doc_values: false,
|
||||
index: false,
|
||||
type: 'keyword',
|
||||
},
|
||||
path_match: 'event.original',
|
||||
},
|
||||
},
|
||||
{
|
||||
ecs_non_indexed_long: {
|
||||
mapping: {
|
||||
doc_values: false,
|
||||
index: false,
|
||||
type: 'long',
|
||||
},
|
||||
path_match: '*.x509.public_key_exponent',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -305,7 +324,7 @@ export default function (providerContext: FtrProviderContext) {
|
|||
},
|
||||
{
|
||||
ecs_geo_point: {
|
||||
path_match: ['location', '*.location'],
|
||||
path_match: '*.geo.location',
|
||||
mapping: {
|
||||
type: 'geo_point',
|
||||
},
|
||||
|
@ -426,6 +445,7 @@ export default function (providerContext: FtrProviderContext) {
|
|||
'event.ingested': {
|
||||
type: 'date',
|
||||
format: 'strict_date_time_no_millis||strict_date_optional_time||epoch_millis',
|
||||
ignore_malformed: false,
|
||||
},
|
||||
'host.architecture': {
|
||||
type: 'keyword',
|
||||
|
@ -508,6 +528,34 @@ export default function (providerContext: FtrProviderContext) {
|
|||
});
|
||||
});
|
||||
|
||||
it('Works correctly when there is an existing datastream with the same name', async () => {
|
||||
const INTEGRATION_NAME_1 = 'myintegration';
|
||||
const DATASET_NAME = 'test';
|
||||
await esClient.transport.request({
|
||||
method: 'POST',
|
||||
path: `logs-${INTEGRATION_NAME_1}.${DATASET_NAME}-default/_doc`,
|
||||
body: {
|
||||
'@timestamp': '2015-01-01',
|
||||
logs_test_name: `${DATASET_NAME}`,
|
||||
data_stream: {
|
||||
dataset: `${INTEGRATION_NAME_1}.${DATASET_NAME}_logs`,
|
||||
namespace: 'default',
|
||||
type: 'logs',
|
||||
},
|
||||
},
|
||||
});
|
||||
await supertest
|
||||
.post(`/api/fleet/epm/custom_integrations`)
|
||||
.set('kbn-xsrf', 'xxxx')
|
||||
.type('application/json')
|
||||
.send({
|
||||
force: true,
|
||||
integrationName: INTEGRATION_NAME_1,
|
||||
datasets: [{ name: `${INTEGRATION_NAME_1}.${DATASET_NAME}`, type: 'logs' }],
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('Throws an error when there is a naming collision with a current package installation', async () => {
|
||||
await supertest
|
||||
.post(`/api/fleet/epm/custom_integrations`)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue