Reapply "[Response Ops][Alerting] Backfill actions schema changes for intermediate release (#204657)

## Summary

Redoing [this PR](https://github.com/elastic/kibana/pull/203184) which
had to be [reverted](https://github.com/elastic/kibana/pull/204218).
This should not be merged until [this update to the task manager v1
schema](https://github.com/elastic/kibana/pull/204413) is released.

## To verify
1. Set `xpack.task_manager.unsafe.exclude_task_types:
['ad_hoc_run-backfill', 'actions:*']` in your Kibana config.
2. Run Kibana on main and create some detection rules that run
frequently, with actions.
3. Schedule a manual run for your detection rules.
- Because of the config, the `action_task_params` SO and the
`ad_hoc_run_task_params` SO will get written but not read yet.
4. Remove the `exclude_task_types` config and "upgrade" to this PR
branch and verify that rules continue to run and that the actions are
triggered and the manual rule runs go through
5. Re-add the `exclude_task_types` config and let the rule run again to
schedule action. Schedule another manual rule run.
6. Remove the `exclude_task_types` config and "downgrade" back to main
and verify that rules continue to run, the action gets triggered and
manual rule runs go through.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Ying Mao 2025-01-07 16:37:01 -05:00 committed by GitHub
parent 28414ce988
commit 11e3a0b77e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 194 additions and 9 deletions

View file

@ -3,7 +3,9 @@
"actionTypeId",
"name"
],
"action_task_params": [],
"action_task_params": [
"apiKeyId"
],
"ad_hoc_run_params": [
"apiKeyId",
"createdAt",
@ -1104,6 +1106,7 @@
"enabled",
"ownerId",
"partition",
"priority",
"retryAt",
"runAt",
"schedule",

View file

@ -17,7 +17,11 @@
},
"action_task_params": {
"dynamic": false,
"properties": {}
"properties": {
"apiKeyId": {
"type": "keyword"
}
}
},
"ad_hoc_run_params": {
"dynamic": false,
@ -3655,6 +3659,9 @@
"partition": {
"type": "integer"
},
"priority": {
"type": "integer"
},
"retryAt": {
"type": "date"
},

View file

@ -57,8 +57,8 @@ describe('checking migration metadata changes on all registered SO types', () =>
expect(hashMap).toMatchInlineSnapshot(`
Object {
"action": "0e6fc0b74c7312a8c11ff6b14437b93a997358b8",
"action_task_params": "b50cb5c8a493881474918e8d4985e61374ca4c30",
"ad_hoc_run_params": "d4e3c5c794151d0a4f5c71e886b2aa638da73ad2",
"action_task_params": "2e475d8b62e2de50b77f58cda309efb537e1d543",
"ad_hoc_run_params": "c7419760e878207231c3c8a25ec4d78360e07bf7",
"alert": "556a03378f5ee1c31593c3a37c66b54555ee14ff",
"api_key_pending_invalidation": "8f5554d1984854011b8392d9a6f7ef985bcac03c",
"apm-custom-dashboards": "b67128f78160c288bd7efe25b2da6e2afd5e82fc",
@ -170,7 +170,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
"synthetics-private-location": "8cecc9e4f39637d2f8244eb7985c0690ceab24be",
"synthetics-privates-locations": "f53d799d5c9bc8454aaa32c6abc99a899b025d5c",
"tag": "e2544392fe6563e215bb677abc8b01c2601ef2dc",
"task": "3c89a7c918d5b896a5f8800f06e9114ad7e7aea3",
"task": "ca8020259e46f713965a754ffae286c02d3cf05d",
"telemetry": "7b00bcf1c7b4f6db1192bb7405a6a63e78b699fd",
"threshold-explorer-view": "175306806f9fc8e13fcc1c8953ec4ba89bda1b70",
"ui-metric": "d227284528fd19904e9d972aea0a13716fc5fe24",

View file

@ -40,6 +40,9 @@ export const actionMappings: SavedObjectsTypeMappingDefinition = {
export const actionTaskParamsMappings: SavedObjectsTypeMappingDefinition = {
dynamic: false,
properties: {
apiKeyId: {
type: 'keyword',
},
// NO NEED TO BE INDEXED
// actionId: {
// type: 'keyword',

View file

@ -6,13 +6,28 @@
*/
import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server';
import { actionTaskParamsSchemaV1 } from '../schemas/action_task_params';
import { actionTaskParamsSchemaV1, actionTaskParamsSchemaV2 } from '../schemas/action_task_params';
export const actionTaskParamsModelVersions: SavedObjectsModelVersionMap = {
'1': {
changes: [],
schemas: {
forwardCompatibility: actionTaskParamsSchemaV1.extends({}, { unknowns: 'ignore' }),
create: actionTaskParamsSchemaV1,
},
},
'2': {
changes: [
{
type: 'mappings_addition',
addedMappings: {
apiKeyId: { type: 'keyword' },
},
},
],
schemas: {
forwardCompatibility: actionTaskParamsSchemaV2.extends({}, { unknowns: 'ignore' }),
create: actionTaskParamsSchemaV2,
},
},
};

View file

@ -6,3 +6,4 @@
*/
export { actionTaskParamsSchema as actionTaskParamsSchemaV1 } from './v1';
export { actionTaskParamsSchema as actionTaskParamsSchemaV2 } from './v2';

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema } from '@kbn/config-schema';
import { actionTaskParamsSchema as actionTaskParamsSchemaV1 } from './v1';
export const actionTaskParamsSchema = actionTaskParamsSchemaV1.extends({
apiKeyId: schema.maybe(schema.string()),
});

View file

@ -15,6 +15,7 @@ export const scheduleBodySchema = schema.arrayOf(
rule_id: schema.string(),
start: schema.string(),
end: schema.maybe(schema.string()),
run_actions: schema.maybe(schema.boolean()),
},
{
validate({ start, end }) {

View file

@ -6,7 +6,10 @@
*/
import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server';
import { rawAdHocRunParamsSchemaV1 } from '../schemas/raw_ad_hoc_run_params';
import {
rawAdHocRunParamsSchemaV1,
rawAdHocRunParamsSchemaV2,
} from '../schemas/raw_ad_hoc_run_params';
export const adHocRunParamsModelVersions: SavedObjectsModelVersionMap = {
'1': {
@ -16,4 +19,11 @@ export const adHocRunParamsModelVersions: SavedObjectsModelVersionMap = {
create: rawAdHocRunParamsSchemaV1,
},
},
'2': {
changes: [],
schemas: {
forwardCompatibility: rawAdHocRunParamsSchemaV2.extends({}, { unknowns: 'ignore' }),
create: rawAdHocRunParamsSchemaV2,
},
},
};

View file

@ -6,3 +6,4 @@
*/
export { rawAdHocRunParamsSchema as rawAdHocRunParamsSchemaV1 } from './v1';
export { rawAdHocRunParamsSchema as rawAdHocRunParamsSchemaV2 } from './v2';

View file

@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { TypeOf } from '@kbn/config-schema';
import { rawAdHocRunParamsSchema } from './v2';
export type RawAdHocRunParams = TypeOf<typeof rawAdHocRunParamsSchema>;

View file

@ -21,7 +21,7 @@ const rawAdHocRunSchedule = schema.object({
runAt: schema.string(),
});
const rawAdHocRunParamsRuleSchema = schema.object({
export const rawAdHocRunParamsRuleSchema = schema.object({
name: schema.string(),
tags: schema.arrayOf(schema.string()),
alertTypeId: schema.string(),

View file

@ -0,0 +1,99 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { schema } from '@kbn/config-schema';
import { FilterStateStore } from '@kbn/es-query';
import {
rawAdHocRunParamsSchema as rawAdHocRunParamsSchemaV1,
rawAdHocRunParamsRuleSchema as rawAdHocRunParamsRuleSchemaV1,
} from './v1';
const ISOWeekdaysSchema = schema.oneOf([
schema.literal(1),
schema.literal(2),
schema.literal(3),
schema.literal(4),
schema.literal(5),
schema.literal(6),
schema.literal(7),
]);
const rawRuleAlertsFilterSchema = schema.object({
query: schema.maybe(
schema.object({
kql: schema.string(),
filters: schema.arrayOf(
schema.object({
query: schema.maybe(schema.recordOf(schema.string(), schema.any())),
meta: schema.object({
alias: schema.maybe(schema.nullable(schema.string())),
disabled: schema.maybe(schema.boolean()),
negate: schema.maybe(schema.boolean()),
controlledBy: schema.maybe(schema.string()),
group: schema.maybe(schema.string()),
index: schema.maybe(schema.string()),
isMultiIndex: schema.maybe(schema.boolean()),
type: schema.maybe(schema.string()),
key: schema.maybe(schema.string()),
params: schema.maybe(schema.any()),
value: schema.maybe(schema.string()),
field: schema.maybe(schema.string()),
relation: schema.maybe(schema.oneOf([schema.literal('OR'), schema.literal('AND')])),
}),
$state: schema.maybe(
schema.object({
store: schema.oneOf([
schema.literal(FilterStateStore.APP_STATE), // change
schema.literal(FilterStateStore.GLOBAL_STATE), // change
]),
})
),
})
),
dsl: schema.string(), // change
})
),
timeframe: schema.maybe(
schema.object({
days: schema.arrayOf(ISOWeekdaysSchema),
hours: schema.object({
start: schema.string(),
end: schema.string(),
}),
timezone: schema.string(),
})
),
});
const rawAdHocRunParamsRuleActionSchema = schema.object({
uuid: schema.string(),
group: schema.maybe(schema.string()),
actionRef: schema.string(),
actionTypeId: schema.string(),
params: schema.recordOf(schema.string(), schema.any()),
frequency: schema.maybe(
schema.object({
summary: schema.boolean(),
notifyWhen: schema.oneOf([
schema.literal('onActionGroupChange'),
schema.literal('onActiveAlert'),
schema.literal('onThrottleInterval'),
]),
throttle: schema.nullable(schema.string()),
})
),
alertsFilter: schema.maybe(rawRuleAlertsFilterSchema),
useAlertDataForTemplate: schema.maybe(schema.boolean()),
});
const rawAdHocRunParamsRuleSchema = rawAdHocRunParamsRuleSchemaV1.extends({
actions: schema.maybe(schema.arrayOf(rawAdHocRunParamsRuleActionSchema)),
});
export const rawAdHocRunParamsSchema = rawAdHocRunParamsSchemaV1.extends({
rule: rawAdHocRunParamsRuleSchema,
});

View file

@ -65,6 +65,9 @@ export const taskMappings: SavedObjectsTypeMappingDefinition = {
partition: {
type: 'integer',
},
priority: {
type: 'integer',
},
},
};

View file

@ -6,7 +6,7 @@
*/
import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server';
import { taskSchemaV1, taskSchemaV2 } from '../schemas/task';
import { taskSchemaV1, taskSchemaV2, taskSchemaV3 } from '../schemas/task';
// IMPORTANT!!!
// When adding new model versions, make sure to manually test
@ -39,4 +39,18 @@ export const taskModelVersions: SavedObjectsModelVersionMap = {
create: taskSchemaV2,
},
},
'3': {
changes: [
{
type: 'mappings_addition',
addedMappings: {
priority: { type: 'integer' },
},
},
],
schemas: {
forwardCompatibility: taskSchemaV3.extends({}, { unknowns: 'ignore' }),
create: taskSchemaV3,
},
},
};

View file

@ -49,3 +49,7 @@ export const taskSchemaV1 = schema.object({
export const taskSchemaV2 = taskSchemaV1.extends({
partition: schema.maybe(schema.number()),
});
export const taskSchemaV3 = taskSchemaV2.extends({
priority: schema.maybe(schema.number()),
});