Skip to content

Commit 0cac49c

Browse files
committed
unlock prebuilt rules upgrade due to deprecated lastRun.outcomeMsg schema
1 parent 7b65a9c commit 0cac49c

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

x-pack/platform/plugins/shared/alerting/server/application/rule/methods/update/update_rule.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4709,4 +4709,53 @@ describe('update()', () => {
47094709
expect(result.artifacts).toBeDefined();
47104710
});
47114711
});
4712+
4713+
describe('rule migration', () => {
4714+
test('migrates legacy lastRun.outcomeMsg string to string[]', async () => {
4715+
unsecuredSavedObjectsClient.create.mockResolvedValueOnce({
4716+
id: '1',
4717+
type: RULE_SAVED_OBJECT_TYPE,
4718+
attributes: {
4719+
enabled: true,
4720+
schedule: { interval: '1m' },
4721+
params: {
4722+
bar: true,
4723+
},
4724+
actions: [],
4725+
lastRun: {
4726+
outcomeMsg: 'Some message',
4727+
},
4728+
revision: 1,
4729+
scheduledTaskId: 'task-123',
4730+
createdAt: new Date().toISOString(),
4731+
updatedAt: new Date().toISOString(),
4732+
},
4733+
references: [],
4734+
});
4735+
4736+
const result = await rulesClient.update({
4737+
id: '1',
4738+
data: {
4739+
schedule: { interval: '1m' },
4740+
name: 'abc',
4741+
tags: ['foo'],
4742+
params: {
4743+
bar: true,
4744+
risk_score: 40,
4745+
severity: 'low',
4746+
},
4747+
actions: [],
4748+
alertDelay: {
4749+
active: 10,
4750+
},
4751+
},
4752+
});
4753+
4754+
expect(result).toMatchObject({
4755+
lastRun: {
4756+
outcomeMsg: ['Some message'],
4757+
},
4758+
});
4759+
});
4760+
});
47124761
});

x-pack/platform/plugins/shared/alerting/server/application/rule/methods/update/update_rule.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ async function updateRuleAttributes<Params extends RuleParams = never>({
316316
updatedBy: username,
317317
updatedAt: new Date().toISOString(),
318318
artifacts: artifactsWithRefs,
319+
...(originalRule.lastRun
320+
? { lastRun: migrateLegacyLastRunOutcomeMsg(originalRule.lastRun) }
321+
: {}),
319322
});
320323

321324
const mappedParams = getMappedParams(updatedParams);
@@ -379,3 +382,25 @@ async function updateRuleAttributes<Params extends RuleParams = never>({
379382
// without fixing all of other solution types
380383
return rule as SanitizedRule<Params>;
381384
}
385+
386+
/**
387+
* Migrates legacy lastRun.outcomeMsg from string to string[]
388+
*
389+
* Rule SO schema forces lastRun.outcomeMsg to be string[].
390+
* However, some rules may have lastRun.outcomeMsg as string after upgrading from 7.x due to
391+
* lack of migration. lastRun.outcomeMsg schema change from string to string[] happened after
392+
* classical migrations were deprecated due to Serverless. And quite often it's not an issue
393+
* as lastRun is absent.
394+
*/
395+
function migrateLegacyLastRunOutcomeMsg<LastRun extends { outcomeMsg?: unknown }>(
396+
lastRun: LastRun
397+
): LastRun {
398+
if (typeof lastRun.outcomeMsg === 'string') {
399+
return {
400+
...lastRun,
401+
outcomeMsg: [lastRun.outcomeMsg],
402+
};
403+
}
404+
405+
return lastRun;
406+
}

0 commit comments

Comments
 (0)