Skip to content

Commit 5acba96

Browse files
authored
Add error handling/retry logic for search source alert tests (elastic#196443)
## Summary Resolves elastic#193842. Adds error handling & retry logic for search source alerts that are causing failures on MKI. ### Checklist - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed
1 parent 75760bb commit 5acba96

File tree

2 files changed

+123
-87
lines changed

2 files changed

+123
-87
lines changed

x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/discover/search_source_alert.ts

+46-40
Original file line numberDiff line numberDiff line change
@@ -45,53 +45,59 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
4545
let connectorId: string;
4646

4747
const createSourceIndex = () =>
48-
es.index({
49-
index: SOURCE_DATA_VIEW,
50-
body: {
51-
settings: { number_of_shards: 1 },
52-
mappings: {
53-
properties: {
54-
'@timestamp': { type: 'date' },
55-
message: { type: 'keyword' },
56-
},
48+
retry.try(() =>
49+
createIndex(SOURCE_DATA_VIEW, {
50+
'@timestamp': { type: 'date' },
51+
message: { type: 'keyword' },
52+
})
53+
);
54+
55+
const createOutputDataIndex = () =>
56+
retry.try(() =>
57+
createIndex(OUTPUT_DATA_VIEW, {
58+
rule_id: { type: 'text' },
59+
rule_name: { type: 'text' },
60+
alert_id: { type: 'text' },
61+
context_link: { type: 'text' },
62+
})
63+
);
64+
65+
async function createIndex(index: string, properties: unknown) {
66+
try {
67+
await es.index({
68+
index,
69+
body: {
70+
settings: { number_of_shards: 1 },
71+
mappings: { properties },
5772
},
58-
},
59-
});
73+
});
74+
} catch (e) {
75+
log.error(`Failed to create index "${index}" with error "${e.message}"`);
76+
}
77+
}
6078

61-
const generateNewDocs = async (docsNumber: number) => {
79+
async function generateNewDocs(docsNumber: number, index = SOURCE_DATA_VIEW) {
6280
const mockMessages = Array.from({ length: docsNumber }, (_, i) => `msg-${i}`);
6381
const dateNow = new Date();
6482
const dateToSet = new Date(dateNow);
6583
dateToSet.setMinutes(dateNow.getMinutes() - 10);
66-
for (const message of mockMessages) {
67-
await es.transport.request({
68-
path: `/${SOURCE_DATA_VIEW}/_doc`,
69-
method: 'POST',
70-
body: {
71-
'@timestamp': dateToSet.toISOString(),
72-
message,
73-
},
74-
});
84+
try {
85+
await Promise.all(
86+
mockMessages.map((message) =>
87+
es.transport.request({
88+
path: `/${index}/_doc`,
89+
method: 'POST',
90+
body: {
91+
'@timestamp': dateToSet.toISOString(),
92+
message,
93+
},
94+
})
95+
)
96+
);
97+
} catch (e) {
98+
log.error(`Failed to generate new docs in "${index}" with error "${e.message}"`);
7599
}
76-
};
77-
78-
const createOutputDataIndex = () =>
79-
es.index({
80-
index: OUTPUT_DATA_VIEW,
81-
body: {
82-
settings: {
83-
number_of_shards: 1,
84-
},
85-
mappings: {
86-
properties: {
87-
rule_id: { type: 'text' },
88-
rule_name: { type: 'text' },
89-
alert_id: { type: 'text' },
90-
context_link: { type: 'text' },
91-
},
92-
},
93-
},
94-
});
100+
}
95101

96102
const deleteAlerts = (alertIds: string[]) =>
97103
asyncForEach(alertIds, async (alertId: string) => {

x-pack/test_serverless/functional/test_suites/common/discover_ml_uptime/discover/search_source_alert.ts

+77-47
Original file line numberDiff line numberDiff line change
@@ -48,53 +48,59 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
4848
let connectorId: string;
4949

5050
const createSourceIndex = () =>
51-
es.index({
52-
index: SOURCE_DATA_VIEW,
53-
body: {
54-
settings: { number_of_shards: 1 },
55-
mappings: {
56-
properties: {
57-
'@timestamp': { type: 'date' },
58-
message: { type: 'keyword' },
59-
},
51+
retry.try(() =>
52+
createIndex(SOURCE_DATA_VIEW, {
53+
'@timestamp': { type: 'date' },
54+
message: { type: 'keyword' },
55+
})
56+
);
57+
58+
const createOutputDataIndex = () =>
59+
retry.try(() =>
60+
createIndex(OUTPUT_DATA_VIEW, {
61+
rule_id: { type: 'text' },
62+
rule_name: { type: 'text' },
63+
alert_id: { type: 'text' },
64+
context_link: { type: 'text' },
65+
})
66+
);
67+
68+
async function createIndex(index: string, properties: unknown) {
69+
try {
70+
await es.index({
71+
index,
72+
body: {
73+
settings: { number_of_shards: 1 },
74+
mappings: { properties },
6075
},
61-
},
62-
});
76+
});
77+
} catch (e) {
78+
log.error(`Failed to create index "${index}" with error "${e.message}"`);
79+
}
80+
}
6381

64-
const generateNewDocs = async (docsNumber: number) => {
82+
async function generateNewDocs(docsNumber: number, index = SOURCE_DATA_VIEW) {
6583
const mockMessages = Array.from({ length: docsNumber }, (_, i) => `msg-${i}`);
6684
const dateNow = new Date();
6785
const dateToSet = new Date(dateNow);
6886
dateToSet.setMinutes(dateNow.getMinutes() - 10);
69-
for (const message of mockMessages) {
70-
await es.transport.request({
71-
path: `/${SOURCE_DATA_VIEW}/_doc`,
72-
method: 'POST',
73-
body: {
74-
'@timestamp': dateToSet.toISOString(),
75-
message,
76-
},
77-
});
87+
try {
88+
await Promise.all(
89+
mockMessages.map((message) =>
90+
es.transport.request({
91+
path: `/${index}/_doc`,
92+
method: 'POST',
93+
body: {
94+
'@timestamp': dateToSet.toISOString(),
95+
message,
96+
},
97+
})
98+
)
99+
);
100+
} catch (e) {
101+
log.error(`Failed to generate new docs in "${index}" with error "${e.message}"`);
78102
}
79-
};
80-
81-
const createOutputDataIndex = () =>
82-
es.index({
83-
index: OUTPUT_DATA_VIEW,
84-
body: {
85-
settings: {
86-
number_of_shards: 1,
87-
},
88-
mappings: {
89-
properties: {
90-
rule_id: { type: 'text' },
91-
rule_name: { type: 'text' },
92-
alert_id: { type: 'text' },
93-
context_link: { type: 'text' },
94-
},
95-
},
96-
},
97-
});
103+
}
98104

99105
const deleteAlerts = (alertIds: string[]) =>
100106
asyncForEach(alertIds, async (alertId: string) => {
@@ -216,7 +222,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
216222

217223
const openDiscoverAlertFlyout = async () => {
218224
await testSubjects.click('discoverAlertsButton');
219-
await testSubjects.click('discoverCreateAlertButton');
225+
// Different create rule buttons in serverless
226+
if (await testSubjects.exists('discoverCreateAlertButton')) {
227+
await testSubjects.click('discoverCreateAlertButton');
228+
} else {
229+
await testSubjects.click('discoverAppMenuCustomThresholdRule');
230+
}
220231
};
221232

222233
const openManagementAlertFlyout = async () => {
@@ -366,8 +377,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
366377
};
367378

368379
describe('Search source Alert', function () {
369-
// see details: https://github.com/elastic/kibana/issues/193842
370-
this.tags(['failsOnMKI', 'skipSvlOblt']);
380+
// Failing: https://github.com/elastic/kibana/issues/203045
381+
this.tags(['skipSvlOblt']);
382+
371383
before(async () => {
372384
await security.testUser.setRoles(['discover_alert']);
373385
await PageObjects.svlCommonPage.loginAsAdmin();
@@ -502,7 +514,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
502514

503515
await testSubjects.click('thresholdPopover');
504516
await testSubjects.setValue('alertThresholdInput0', '1');
505-
await testSubjects.click('saveEditedRuleButton');
517+
518+
// Different save buttons in serverless
519+
if (await testSubjects.exists('saveEditedRuleButton')) {
520+
await testSubjects.click('saveEditedRuleButton');
521+
} else {
522+
await testSubjects.click('rulePageFooterSaveButton');
523+
}
506524
await PageObjects.header.waitUntilLoadingHasFinished();
507525

508526
await openAlertResults(RULE_NAME);
@@ -652,8 +670,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
652670
await PageObjects.header.waitUntilLoadingHasFinished();
653671

654672
await retry.waitFor('rule name value is correct', async () => {
655-
await testSubjects.setValue('ruleNameInput', newAlert);
656-
const ruleName = await testSubjects.getAttribute('ruleNameInput', 'value');
673+
let ruleName;
674+
// Rule name input is different in serverless
675+
if (await testSubjects.exists('ruleNameInput')) {
676+
await testSubjects.setValue('ruleNameInput', newAlert);
677+
ruleName = await testSubjects.getAttribute('ruleNameInput', 'value');
678+
} else {
679+
await testSubjects.setValue('ruleDetailsNameInput', newAlert);
680+
ruleName = await testSubjects.getAttribute('ruleDetailsNameInput', 'value');
681+
}
657682
return ruleName === newAlert;
658683
});
659684

@@ -677,7 +702,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
677702
await comboBox.set('ruleFormConsumerSelect', 'Stack Rules');
678703
}
679704

680-
await testSubjects.click('saveRuleButton');
705+
// Save rule button is different in serverless
706+
if (await testSubjects.exists('saveRuleButton')) {
707+
await testSubjects.click('saveRuleButton');
708+
} else {
709+
await testSubjects.click('rulePageFooterSaveButton');
710+
}
681711

682712
await retry.waitFor('confirmation modal', async () => {
683713
return await testSubjects.exists('confirmModalConfirmButton');

0 commit comments

Comments
 (0)