[Alerting] Renaming AlertType to RuleType and updating Alerting Task Runner (#120661)

* Renaming AlertType to RuleType and updating Alerting Task Runner

* Fixing types

* Fixing types

* holy cannoli

* Fixing types

* Fixing types and tests

* Fixing types and tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
ymao1 2021-12-09 09:21:38 -05:00 committed by GitHub
parent f14540ff63
commit 7c27163d6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
82 changed files with 1163 additions and 1202 deletions

View file

@ -15,7 +15,7 @@ Rules and connectors log to the Kibana logger with tags of [alerting] and [actio
[source, txt] [source, txt]
-------------------------------------------------- --------------------------------------------------
server log [11:39:40.389] [error][alerting][alerting][plugins][plugins] Executing Alert "5b6237b0-c6f6-11eb-b0ff-a1a0cbcf29b6" has resulted in Error: Saved object [action/fdbc8610-c6f5-11eb-b0ff-a1a0cbcf29b6] not found server log [11:39:40.389] [error][alerting][alerting][plugins][plugins] Executing Rule "5b6237b0-c6f6-11eb-b0ff-a1a0cbcf29b6" has resulted in Error: Saved object [action/fdbc8610-c6f5-11eb-b0ff-a1a0cbcf29b6] not found
-------------------------------------------------- --------------------------------------------------
Some of the resources, such as saved objects and API keys, may no longer be available or valid, yielding error messages about those missing resources. Some of the resources, such as saved objects and API keys, may no longer be available or valid, yielding error messages about those missing resources.

View file

@ -170,7 +170,7 @@ And see the errors for the rules you might provide the next search query:
} }
], ],
}, },
"message": "alert executed: .index-threshold:30d856c0-b14b-11eb-9a7c-9df284da9f99: 'test'", "message": "rule executed: .index-threshold:30d856c0-b14b-11eb-9a7c-9df284da9f99: 'test'",
"error" : { "error" : {
"message" : "Saved object [action/ef0e2530-b14a-11eb-9a7c-9df284da9f99] not found" "message" : "Saved object [action/ef0e2530-b14a-11eb-9a7c-9df284da9f99] not found"
}, },

View file

@ -1020,7 +1020,7 @@ This log message tells us that when Task Manager was running one of our rules, i
For example, in this case, wed expect to see a corresponding log line from the Alerting framework itself, saying that the rule failed. You should look in the Kibana log for a line similar to the log line below (probably shortly before the Task Manager log line): For example, in this case, wed expect to see a corresponding log line from the Alerting framework itself, saying that the rule failed. You should look in the Kibana log for a line similar to the log line below (probably shortly before the Task Manager log line):
Executing Alert "27559295-44e4-4983-aa1b-94fe043ab4f9" has resulted in Error: Unable to load resource /api/something Executing Rule "27559295-44e4-4983-aa1b-94fe043ab4f9" has resulted in Error: Unable to load resource /api/something
This would confirm that the error did in fact happen in the rule itself (rather than the Task Manager) and it would help us pin-point the specific ID of the rule which failed: 27559295-44e4-4983-aa1b-94fe043ab4f9 This would confirm that the error did in fact happen in the rule itself (rather than the Task Manager) and it would help us pin-point the specific ID of the rule which failed: 27559295-44e4-4983-aa1b-94fe043ab4f9

View file

@ -24,7 +24,7 @@ import { isEmpty } from 'lodash';
import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
import { import {
Alert, Alert,
AlertTaskState, RuleTaskState,
LEGACY_BASE_ALERT_API_PATH, LEGACY_BASE_ALERT_API_PATH,
} from '../../../../plugins/alerting/common'; } from '../../../../plugins/alerting/common';
@ -34,7 +34,7 @@ type Props = RouteComponentProps & {
}; };
export const ViewAlertPage = withRouter(({ http, id }: Props) => { export const ViewAlertPage = withRouter(({ http, id }: Props) => {
const [alert, setAlert] = useState<Alert | null>(null); const [alert, setAlert] = useState<Alert | null>(null);
const [alertState, setAlertState] = useState<AlertTaskState | null>(null); const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
useEffect(() => { useEffect(() => {
if (!alert) { if (!alert) {
@ -42,7 +42,7 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => {
} }
if (!alertState) { if (!alertState) {
http http
.get<AlertTaskState | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`) .get<RuleTaskState | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`)
.then(setAlertState); .then(setAlertState);
} }
}, [alert, alertState, http, id]); }, [alert, alertState, http, id]);

View file

@ -26,7 +26,7 @@ import { isEmpty } from 'lodash';
import { ALERTING_EXAMPLE_APP_ID, AlwaysFiringParams } from '../../common/constants'; import { ALERTING_EXAMPLE_APP_ID, AlwaysFiringParams } from '../../common/constants';
import { import {
Alert, Alert,
AlertTaskState, RuleTaskState,
LEGACY_BASE_ALERT_API_PATH, LEGACY_BASE_ALERT_API_PATH,
} from '../../../../plugins/alerting/common'; } from '../../../../plugins/alerting/common';
@ -40,7 +40,7 @@ function hasCraft(state: any): state is { craft: string } {
} }
export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => { export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
const [alert, setAlert] = useState<Alert<AlwaysFiringParams> | null>(null); const [alert, setAlert] = useState<Alert<AlwaysFiringParams> | null>(null);
const [alertState, setAlertState] = useState<AlertTaskState | null>(null); const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
useEffect(() => { useEffect(() => {
if (!alert) { if (!alert) {
@ -50,7 +50,7 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
} }
if (!alertState) { if (!alertState) {
http http
.get<AlertTaskState | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`) .get<RuleTaskState | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`)
.then(setAlertState); .then(setAlertState);
} }
}, [alert, alertState, http, id]); }, [alert, alertState, http, id]);

View file

@ -7,7 +7,7 @@
import uuid from 'uuid'; import uuid from 'uuid';
import { range } from 'lodash'; import { range } from 'lodash';
import { AlertType } from '../../../../plugins/alerting/server'; import { RuleType } from '../../../../plugins/alerting/server';
import { import {
DEFAULT_INSTANCES_TO_GENERATE, DEFAULT_INSTANCES_TO_GENERATE,
ALERTING_EXAMPLE_APP_ID, ALERTING_EXAMPLE_APP_ID,
@ -37,7 +37,7 @@ function getTShirtSizeByIdAndThreshold(
return DEFAULT_ACTION_GROUP; return DEFAULT_ACTION_GROUP;
} }
export const alertType: AlertType< export const alertType: RuleType<
AlwaysFiringParams, AlwaysFiringParams,
never, never,
{ count?: number }, { count?: number },

View file

@ -6,7 +6,7 @@
*/ */
import axios from 'axios'; import axios from 'axios';
import { AlertType } from '../../../../plugins/alerting/server'; import { RuleType } from '../../../../plugins/alerting/server';
import { Operator, Craft, ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; import { Operator, Craft, ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
interface PeopleInSpace { interface PeopleInSpace {
@ -39,7 +39,7 @@ function getCraftFilter(craft: string) {
craft === Craft.OuterSpace ? true : craft === person.craft; craft === Craft.OuterSpace ? true : craft === person.craft;
} }
export const alertType: AlertType< export const alertType: RuleType<
{ outerSpaceCapacity: number; craft: string; op: string }, { outerSpaceCapacity: number; craft: string; op: string },
never, never,
{ peopleInSpace: number }, { peopleInSpace: number },

View file

@ -230,7 +230,7 @@ interface MyRuleTypeAlertContext extends AlertInstanceContext {
type MyRuleTypeActionGroups = 'default' | 'warning'; type MyRuleTypeActionGroups = 'default' | 'warning';
const myRuleType: AlertType< const myRuleType: RuleType<
MyRuleTypeParams, MyRuleTypeParams,
MyRuleTypeExtractedParams, MyRuleTypeExtractedParams,
MyRuleTypeState, MyRuleTypeState,

View file

@ -6,7 +6,7 @@
*/ */
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { ActionGroup } from './alert_type'; import { ActionGroup } from './rule_type';
export type DefaultActionGroupId = 'default'; export type DefaultActionGroupId = 'default';

View file

@ -11,9 +11,9 @@
import { AlertsHealth } from './alert'; import { AlertsHealth } from './alert';
export * from './alert'; export * from './alert';
export * from './alert_type'; export * from './rule_type';
export * from './alert_instance'; export * from './alert_instance';
export * from './alert_task_instance'; export * from './rule_task_instance';
export * from './alert_navigation'; export * from './alert_navigation';
export * from './alert_summary'; export * from './alert_summary';
export * from './builtin_action_groups'; export * from './builtin_action_groups';

View file

@ -9,15 +9,15 @@ import * as t from 'io-ts';
import { rawAlertInstance } from './alert_instance'; import { rawAlertInstance } from './alert_instance';
import { DateFromString } from './date_from_string'; import { DateFromString } from './date_from_string';
export const alertStateSchema = t.partial({ export const ruleStateSchema = t.partial({
alertTypeState: t.record(t.string, t.unknown), alertTypeState: t.record(t.string, t.unknown),
alertInstances: t.record(t.string, rawAlertInstance), alertInstances: t.record(t.string, rawAlertInstance),
previousStartedAt: t.union([t.null, DateFromString]), previousStartedAt: t.union([t.null, DateFromString]),
}); });
export type AlertTaskState = t.TypeOf<typeof alertStateSchema>; export type RuleTaskState = t.TypeOf<typeof ruleStateSchema>;
export const alertParamsSchema = t.intersection([ export const ruleParamsSchema = t.intersection([
t.type({ t.type({
alertId: t.string, alertId: t.string,
}), }),
@ -25,4 +25,4 @@ export const alertParamsSchema = t.intersection([
spaceId: t.string, spaceId: t.string,
}), }),
]); ]);
export type AlertTaskParams = t.TypeOf<typeof alertParamsSchema>; export type RuleTaskParams = t.TypeOf<typeof ruleParamsSchema>;

View file

@ -8,7 +8,7 @@
import { LicenseType } from '../../licensing/common/types'; import { LicenseType } from '../../licensing/common/types';
import { RecoveredActionGroupId, DefaultActionGroupId } from './builtin_action_groups'; import { RecoveredActionGroupId, DefaultActionGroupId } from './builtin_action_groups';
export interface AlertType< export interface RuleType<
ActionGroupIds extends Exclude<string, RecoveredActionGroupId> = DefaultActionGroupId, ActionGroupIds extends Exclude<string, RecoveredActionGroupId> = DefaultActionGroupId,
RecoveryActionGroupId extends string = RecoveredActionGroupId RecoveryActionGroupId extends string = RecoveredActionGroupId
> { > {

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
import { AlertType, RecoveredActionGroup } from '../common'; import { RuleType, RecoveredActionGroup } from '../common';
import { httpServiceMock } from '../../../../src/core/public/mocks'; import { httpServiceMock } from '../../../../src/core/public/mocks';
import { loadAlert, loadAlertType, loadAlertTypes } from './alert_api'; import { loadAlert, loadAlertType, loadAlertTypes } from './alert_api';
import uuid from 'uuid'; import uuid from 'uuid';
@ -16,7 +16,7 @@ beforeEach(() => jest.resetAllMocks());
describe('loadAlertTypes', () => { describe('loadAlertTypes', () => {
test('should call get alert types API', async () => { test('should call get alert types API', async () => {
const resolvedValue: AlertType[] = [ const resolvedValue: RuleType[] = [
{ {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
@ -43,7 +43,7 @@ describe('loadAlertTypes', () => {
describe('loadAlertType', () => { describe('loadAlertType', () => {
test('should call get alert types API', async () => { test('should call get alert types API', async () => {
const alertType: AlertType = { const alertType: RuleType = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionVariables: ['var1'], actionVariables: ['var1'],
@ -66,7 +66,7 @@ describe('loadAlertType', () => {
}); });
test('should find the required alertType', async () => { test('should find the required alertType', async () => {
const alertType: AlertType = { const alertType: RuleType = {
id: 'test-another', id: 'test-another',
name: 'Test Another', name: 'Test Another',
actionVariables: [], actionVariables: [],

View file

@ -7,9 +7,9 @@
import { HttpSetup } from 'kibana/public'; import { HttpSetup } from 'kibana/public';
import { LEGACY_BASE_ALERT_API_PATH } from '../common'; import { LEGACY_BASE_ALERT_API_PATH } from '../common';
import type { Alert, AlertType } from '../common'; import type { Alert, RuleType } from '../common';
export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise<AlertType[]> { export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise<RuleType[]> {
return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`); return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`);
} }
@ -18,11 +18,11 @@ export async function loadAlertType({
id, id,
}: { }: {
http: HttpSetup; http: HttpSetup;
id: AlertType['id']; id: RuleType['id'];
}): Promise<AlertType | undefined> { }): Promise<RuleType | undefined> {
const alertTypes = (await http.get( const alertTypes = (await http.get(
`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types` `${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`
)) as AlertType[]; )) as RuleType[];
return alertTypes.find((type) => type.id === id); return alertTypes.find((type) => type.id === id);
} }

View file

@ -6,12 +6,12 @@
*/ */
import { AlertNavigationRegistry } from './alert_navigation_registry'; import { AlertNavigationRegistry } from './alert_navigation_registry';
import { AlertType, RecoveredActionGroup, SanitizedAlert } from '../../common'; import { RuleType, RecoveredActionGroup, SanitizedAlert } from '../../common';
import uuid from 'uuid'; import uuid from 'uuid';
beforeEach(() => jest.resetAllMocks()); beforeEach(() => jest.resetAllMocks());
const mockAlertType = (id: string): AlertType => ({ const mockAlertType = (id: string): RuleType => ({
id, id,
name: id, name: id,
actionGroups: [], actionGroups: [],

View file

@ -6,7 +6,7 @@
*/ */
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { AlertType } from '../../common'; import { RuleType } from '../../common';
import { AlertNavigationHandler } from './types'; import { AlertNavigationHandler } from './types';
const DEFAULT_HANDLER = Symbol('*'); const DEFAULT_HANDLER = Symbol('*');
@ -14,7 +14,7 @@ export class AlertNavigationRegistry {
private readonly alertNavigations: Map<string, Map<string | symbol, AlertNavigationHandler>> = private readonly alertNavigations: Map<string, Map<string | symbol, AlertNavigationHandler>> =
new Map(); new Map();
public has(consumer: string, alertType: AlertType) { public has(consumer: string, alertType: RuleType) {
return this.hasTypedHandler(consumer, alertType.id) || this.hasDefaultHandler(consumer); return this.hasTypedHandler(consumer, alertType.id) || this.hasDefaultHandler(consumer);
} }
@ -70,7 +70,7 @@ export class AlertNavigationRegistry {
consumerNavigations.set(ruleTypeId, handler); consumerNavigations.set(ruleTypeId, handler);
} }
public get(consumer: string, alertType: AlertType): AlertNavigationHandler { public get(consumer: string, alertType: RuleType): AlertNavigationHandler {
if (this.has(consumer, alertType)) { if (this.has(consumer, alertType)) {
const consumerHandlers = this.alertNavigations.get(consumer)!; const consumerHandlers = this.alertNavigations.get(consumer)!;
return (consumerHandlers.get(alertType.id) ?? consumerHandlers.get(DEFAULT_HANDLER))!; return (consumerHandlers.get(alertType.id) ?? consumerHandlers.get(DEFAULT_HANDLER))!;

View file

@ -6,7 +6,7 @@
*/ */
import { ISavedObjectsRepository, SavedObjectsServiceStart } from 'src/core/server'; import { ISavedObjectsRepository, SavedObjectsServiceStart } from 'src/core/server';
import { AlertsHealth, HealthStatus, RawAlert, AlertExecutionStatusErrorReasons } from '../types'; import { AlertsHealth, HealthStatus, RawRule, AlertExecutionStatusErrorReasons } from '../types';
export const getHealth = async ( export const getHealth = async (
internalSavedObjectsRepository: ISavedObjectsRepository internalSavedObjectsRepository: ISavedObjectsRepository
@ -26,7 +26,7 @@ export const getHealth = async (
}, },
}; };
const { saved_objects: decryptErrorData } = await internalSavedObjectsRepository.find<RawAlert>({ const { saved_objects: decryptErrorData } = await internalSavedObjectsRepository.find<RawRule>({
filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Decrypt}`, filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Decrypt}`,
fields: ['executionStatus'], fields: ['executionStatus'],
type: 'alert', type: 'alert',
@ -44,7 +44,7 @@ export const getHealth = async (
}; };
} }
const { saved_objects: executeErrorData } = await internalSavedObjectsRepository.find<RawAlert>({ const { saved_objects: executeErrorData } = await internalSavedObjectsRepository.find<RawRule>({
filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Execute}`, filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Execute}`,
fields: ['executionStatus'], fields: ['executionStatus'],
type: 'alert', type: 'alert',
@ -62,7 +62,7 @@ export const getHealth = async (
}; };
} }
const { saved_objects: readErrorData } = await internalSavedObjectsRepository.find<RawAlert>({ const { saved_objects: readErrorData } = await internalSavedObjectsRepository.find<RawRule>({
filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Read}`, filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Read}`,
fields: ['executionStatus'], fields: ['executionStatus'],
type: 'alert', type: 'alert',
@ -80,7 +80,7 @@ export const getHealth = async (
}; };
} }
const { saved_objects: noErrorData } = await internalSavedObjectsRepository.find<RawAlert>({ const { saved_objects: noErrorData } = await internalSavedObjectsRepository.find<RawRule>({
filter: 'not alert.attributes.executionStatus.status:error', filter: 'not alert.attributes.executionStatus.status:error',
fields: ['executionStatus'], fields: ['executionStatus'],
type: 'alert', type: 'alert',

View file

@ -14,7 +14,7 @@ import { AlertsConfigType } from './types';
export type RulesClient = PublicMethodsOf<RulesClientClass>; export type RulesClient = PublicMethodsOf<RulesClientClass>;
export type { export type {
AlertType, RuleType,
ActionGroup, ActionGroup,
ActionGroupIdsOf, ActionGroupIdsOf,
AlertingPlugin, AlertingPlugin,

View file

@ -6,11 +6,11 @@
*/ */
import { createAlertEventLogRecordObject } from './create_alert_event_log_record_object'; import { createAlertEventLogRecordObject } from './create_alert_event_log_record_object';
import { UntypedNormalizedAlertType } from '../rule_type_registry'; import { UntypedNormalizedRuleType } from '../rule_type_registry';
import { RecoveredActionGroup } from '../types'; import { RecoveredActionGroup } from '../types';
describe('createAlertEventLogRecordObject', () => { describe('createAlertEventLogRecordObject', () => {
const ruleType: jest.Mocked<UntypedNormalizedAlertType> = { const ruleType: jest.Mocked<UntypedNormalizedRuleType> = {
id: 'test', id: 'test',
name: 'My test alert', name: 'My test alert',
actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup], actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup],

View file

@ -7,13 +7,13 @@
import { AlertInstanceState } from '../types'; import { AlertInstanceState } from '../types';
import { IEvent } from '../../../event_log/server'; import { IEvent } from '../../../event_log/server';
import { UntypedNormalizedAlertType } from '../rule_type_registry'; import { UntypedNormalizedRuleType } from '../rule_type_registry';
export type Event = Exclude<IEvent, undefined>; export type Event = Exclude<IEvent, undefined>;
interface CreateAlertEventLogRecordParams { interface CreateAlertEventLogRecordParams {
ruleId: string; ruleId: string;
ruleType: UntypedNormalizedAlertType; ruleType: UntypedNormalizedRuleType;
action: string; action: string;
ruleName?: string; ruleName?: string;
instanceId?: string; instanceId?: string;

View file

@ -5,6 +5,6 @@
* 2.0. * 2.0.
*/ */
export function getAlertTypeFeatureUsageName(alertTypeName: string) { export function getRuleTypeFeatureUsageName(ruleTypeName: string) {
return `Alert: ${alertTypeName}`; return `Rule: ${ruleTypeName}`;
} }

View file

@ -8,7 +8,7 @@
export { parseDuration, validateDurationSchema } from '../../common/parse_duration'; export { parseDuration, validateDurationSchema } from '../../common/parse_duration';
export type { ILicenseState } from './license_state'; export type { ILicenseState } from './license_state';
export { LicenseState } from './license_state'; export { LicenseState } from './license_state';
export { validateAlertTypeParams } from './validate_alert_type_params'; export { validateRuleTypeParams } from './validate_rule_type_params';
export { getAlertNotifyWhenType } from './get_alert_notify_when_type'; export { getAlertNotifyWhenType } from './get_alert_notify_when_type';
export { verifyApiAccess } from './license_api_access'; export { verifyApiAccess } from './license_api_access';
export { ErrorWithReason, getReasonFromError, isErrorWithReason } from './error_with_reason'; export { ErrorWithReason, getReasonFromError, isErrorWithReason } from './error_with_reason';
@ -21,6 +21,6 @@ export { AlertTypeDisabledError, isErrorThatHandlesItsOwnResponse } from './erro
export { export {
executionStatusFromState, executionStatusFromState,
executionStatusFromError, executionStatusFromError,
alertExecutionStatusToRaw, ruleExecutionStatusToRaw,
alertExecutionStatusFromRaw, ruleExecutionStatusFromRaw,
} from './alert_execution_status'; } from './rule_execution_status';

View file

@ -11,8 +11,8 @@ export const createLicenseStateMock = () => {
const licenseState: jest.Mocked<ILicenseState> = { const licenseState: jest.Mocked<ILicenseState> = {
clean: jest.fn(), clean: jest.fn(),
getLicenseInformation: jest.fn(), getLicenseInformation: jest.fn(),
ensureLicenseForAlertType: jest.fn(), ensureLicenseForRuleType: jest.fn(),
getLicenseCheckForAlertType: jest.fn().mockResolvedValue({ getLicenseCheckForRuleType: jest.fn().mockResolvedValue({
isValid: true, isValid: true,
}), }),
checkLicense: jest.fn().mockResolvedValue({ checkLicense: jest.fn().mockResolvedValue({

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
import { AlertType } from '../types'; import { RuleType } from '../types';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { LicenseState, ILicenseState } from './license_state'; import { LicenseState, ILicenseState } from './license_state';
import { licensingMock } from '../../../licensing/server/mocks'; import { licensingMock } from '../../../licensing/server/mocks';
@ -53,11 +53,11 @@ describe('checkLicense()', () => {
}); });
}); });
describe('getLicenseCheckForAlertType', () => { describe('getLicenseCheckForRuleType', () => {
let license: Subject<ILicense>; let license: Subject<ILicense>;
let licenseState: ILicenseState; let licenseState: ILicenseState;
const mockNotifyUsage = jest.fn(); const mockNotifyUsage = jest.fn();
const alertType: AlertType<never, never, never, never, never, 'default', 'recovered'> = { const ruleType: RuleType<never, never, never, never, never, 'default', 'recovered'> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -82,10 +82,10 @@ describe('getLicenseCheckForAlertType', () => {
test('should return false when license not defined', () => { test('should return false when license not defined', () => {
expect( expect(
licenseState.getLicenseCheckForAlertType( licenseState.getLicenseCheckForRuleType(
alertType.id, ruleType.id,
alertType.name, ruleType.name,
alertType.minimumLicenseRequired ruleType.minimumLicenseRequired
) )
).toEqual({ ).toEqual({
isValid: false, isValid: false,
@ -96,10 +96,10 @@ describe('getLicenseCheckForAlertType', () => {
test('should return false when license not available', () => { test('should return false when license not available', () => {
license.next(createUnavailableLicense()); license.next(createUnavailableLicense());
expect( expect(
licenseState.getLicenseCheckForAlertType( licenseState.getLicenseCheckForRuleType(
alertType.id, ruleType.id,
alertType.name, ruleType.name,
alertType.minimumLicenseRequired ruleType.minimumLicenseRequired
) )
).toEqual({ ).toEqual({
isValid: false, isValid: false,
@ -111,10 +111,10 @@ describe('getLicenseCheckForAlertType', () => {
const expiredLicense = licensingMock.createLicense({ license: { status: 'expired' } }); const expiredLicense = licensingMock.createLicense({ license: { status: 'expired' } });
license.next(expiredLicense); license.next(expiredLicense);
expect( expect(
licenseState.getLicenseCheckForAlertType( licenseState.getLicenseCheckForRuleType(
alertType.id, ruleType.id,
alertType.name, ruleType.name,
alertType.minimumLicenseRequired ruleType.minimumLicenseRequired
) )
).toEqual({ ).toEqual({
isValid: false, isValid: false,
@ -128,10 +128,10 @@ describe('getLicenseCheckForAlertType', () => {
}); });
license.next(basicLicense); license.next(basicLicense);
expect( expect(
licenseState.getLicenseCheckForAlertType( licenseState.getLicenseCheckForRuleType(
alertType.id, ruleType.id,
alertType.name, ruleType.name,
alertType.minimumLicenseRequired ruleType.minimumLicenseRequired
) )
).toEqual({ ).toEqual({
isValid: false, isValid: false,
@ -145,10 +145,10 @@ describe('getLicenseCheckForAlertType', () => {
}); });
license.next(goldLicense); license.next(goldLicense);
expect( expect(
licenseState.getLicenseCheckForAlertType( licenseState.getLicenseCheckForRuleType(
alertType.id, ruleType.id,
alertType.name, ruleType.name,
alertType.minimumLicenseRequired ruleType.minimumLicenseRequired
) )
).toEqual({ ).toEqual({
isValid: true, isValid: true,
@ -160,7 +160,7 @@ describe('getLicenseCheckForAlertType', () => {
license: { status: 'active', type: 'gold' }, license: { status: 'active', type: 'gold' },
}); });
license.next(goldLicense); license.next(goldLicense);
licenseState.getLicenseCheckForAlertType(alertType.id, alertType.name, 'gold'); licenseState.getLicenseCheckForRuleType(ruleType.id, ruleType.name, 'gold');
expect(mockNotifyUsage).not.toHaveBeenCalled(); expect(mockNotifyUsage).not.toHaveBeenCalled();
}); });
@ -169,7 +169,7 @@ describe('getLicenseCheckForAlertType', () => {
license: { status: 'active', type: 'basic' }, license: { status: 'active', type: 'basic' },
}); });
license.next(basicLicense); license.next(basicLicense);
licenseState.getLicenseCheckForAlertType(alertType.id, alertType.name, 'basic'); licenseState.getLicenseCheckForRuleType(ruleType.id, ruleType.name, 'basic');
expect(mockNotifyUsage).not.toHaveBeenCalled(); expect(mockNotifyUsage).not.toHaveBeenCalled();
}); });
@ -178,21 +178,21 @@ describe('getLicenseCheckForAlertType', () => {
license: { status: 'active', type: 'gold' }, license: { status: 'active', type: 'gold' },
}); });
license.next(goldLicense); license.next(goldLicense);
licenseState.getLicenseCheckForAlertType( licenseState.getLicenseCheckForRuleType(
alertType.id, ruleType.id,
alertType.name, ruleType.name,
alertType.minimumLicenseRequired, ruleType.minimumLicenseRequired,
{ notifyUsage: true } { notifyUsage: true }
); );
expect(mockNotifyUsage).toHaveBeenCalledWith('Alert: Test'); expect(mockNotifyUsage).toHaveBeenCalledWith('Rule: Test');
}); });
}); });
describe('ensureLicenseForAlertType()', () => { describe('ensureLicenseForRuleType()', () => {
let license: Subject<ILicense>; let license: Subject<ILicense>;
let licenseState: ILicenseState; let licenseState: ILicenseState;
const mockNotifyUsage = jest.fn(); const mockNotifyUsage = jest.fn();
const alertType: AlertType<never, never, never, never, never, string, string> = { const ruleType: RuleType<never, never, never, never, never, string, string> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -217,18 +217,18 @@ describe('ensureLicenseForAlertType()', () => {
test('should throw when license not defined', () => { test('should throw when license not defined', () => {
expect(() => expect(() =>
licenseState.ensureLicenseForAlertType(alertType) licenseState.ensureLicenseForRuleType(ruleType)
).toThrowErrorMatchingInlineSnapshot( ).toThrowErrorMatchingInlineSnapshot(
`"Alert type test is disabled because license information is not available at this time."` `"Rule type test is disabled because license information is not available at this time."`
); );
}); });
test('should throw when license not available', () => { test('should throw when license not available', () => {
license.next(createUnavailableLicense()); license.next(createUnavailableLicense());
expect(() => expect(() =>
licenseState.ensureLicenseForAlertType(alertType) licenseState.ensureLicenseForRuleType(ruleType)
).toThrowErrorMatchingInlineSnapshot( ).toThrowErrorMatchingInlineSnapshot(
`"Alert type test is disabled because license information is not available at this time."` `"Rule type test is disabled because license information is not available at this time."`
); );
}); });
@ -236,9 +236,9 @@ describe('ensureLicenseForAlertType()', () => {
const expiredLicense = licensingMock.createLicense({ license: { status: 'expired' } }); const expiredLicense = licensingMock.createLicense({ license: { status: 'expired' } });
license.next(expiredLicense); license.next(expiredLicense);
expect(() => expect(() =>
licenseState.ensureLicenseForAlertType(alertType) licenseState.ensureLicenseForRuleType(ruleType)
).toThrowErrorMatchingInlineSnapshot( ).toThrowErrorMatchingInlineSnapshot(
`"Alert type test is disabled because your basic license has expired."` `"Rule type test is disabled because your basic license has expired."`
); );
}); });
@ -248,9 +248,9 @@ describe('ensureLicenseForAlertType()', () => {
}); });
license.next(basicLicense); license.next(basicLicense);
expect(() => expect(() =>
licenseState.ensureLicenseForAlertType(alertType) licenseState.ensureLicenseForRuleType(ruleType)
).toThrowErrorMatchingInlineSnapshot( ).toThrowErrorMatchingInlineSnapshot(
`"Alert test is disabled because it requires a Gold license. Go to License Management to view upgrade options."` `"Rule test is disabled because it requires a Gold license. Go to License Management to view upgrade options."`
); );
}); });
@ -259,7 +259,7 @@ describe('ensureLicenseForAlertType()', () => {
license: { status: 'active', type: 'gold' }, license: { status: 'active', type: 'gold' },
}); });
license.next(goldLicense); license.next(goldLicense);
licenseState.ensureLicenseForAlertType(alertType); licenseState.ensureLicenseForRuleType(ruleType);
}); });
test('should call notifyUsage', () => { test('should call notifyUsage', () => {
@ -267,8 +267,8 @@ describe('ensureLicenseForAlertType()', () => {
license: { status: 'active', type: 'gold' }, license: { status: 'active', type: 'gold' },
}); });
license.next(goldLicense); license.next(goldLicense);
licenseState.ensureLicenseForAlertType(alertType); licenseState.ensureLicenseForRuleType(ruleType);
expect(mockNotifyUsage).toHaveBeenCalledWith('Alert: Test'); expect(mockNotifyUsage).toHaveBeenCalledWith('Rule: Test');
}); });
}); });

View file

@ -14,9 +14,9 @@ import { Observable, Subscription } from 'rxjs';
import { LicensingPluginStart } from '../../../licensing/server'; import { LicensingPluginStart } from '../../../licensing/server';
import { ILicense, LicenseType } from '../../../licensing/common/types'; import { ILicense, LicenseType } from '../../../licensing/common/types';
import { PLUGIN } from '../constants/plugin'; import { PLUGIN } from '../constants/plugin';
import { getAlertTypeFeatureUsageName } from './get_alert_type_feature_usage_name'; import { getRuleTypeFeatureUsageName } from './get_rule_type_feature_usage_name';
import { import {
AlertType, RuleType,
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
AlertInstanceState, AlertInstanceState,
@ -68,21 +68,21 @@ export class LicenseState {
this._notifyUsage = notifyUsage; this._notifyUsage = notifyUsage;
} }
public getLicenseCheckForAlertType( public getLicenseCheckForRuleType(
alertTypeId: string, ruleTypeId: string,
alertTypeName: string, ruleTypeName: string,
minimumLicenseRequired: LicenseType, minimumLicenseRequired: LicenseType,
{ notifyUsage }: { notifyUsage: boolean } = { notifyUsage: false } { notifyUsage }: { notifyUsage: boolean } = { notifyUsage: false }
): { isValid: true } | { isValid: false; reason: 'unavailable' | 'expired' | 'invalid' } { ): { isValid: true } | { isValid: false; reason: 'unavailable' | 'expired' | 'invalid' } {
if (notifyUsage) { if (notifyUsage) {
this.notifyUsage(alertTypeName, minimumLicenseRequired); this.notifyUsage(ruleTypeName, minimumLicenseRequired);
} }
if (!this.license?.isAvailable) { if (!this.license?.isAvailable) {
return { isValid: false, reason: 'unavailable' }; return { isValid: false, reason: 'unavailable' };
} }
const check = this.license.check(alertTypeId, minimumLicenseRequired); const check = this.license.check(ruleTypeId, minimumLicenseRequired);
switch (check.state) { switch (check.state) {
case 'expired': case 'expired':
@ -98,10 +98,10 @@ export class LicenseState {
} }
} }
private notifyUsage(alertTypeName: string, minimumLicenseRequired: LicenseType) { private notifyUsage(ruleTypeName: string, minimumLicenseRequired: LicenseType) {
// No need to notify usage on basic alert types // No need to notify usage on basic alert types
if (this._notifyUsage && minimumLicenseRequired !== 'basic') { if (this._notifyUsage && minimumLicenseRequired !== 'basic') {
this._notifyUsage(getAlertTypeFeatureUsageName(alertTypeName)); this._notifyUsage(getRuleTypeFeatureUsageName(ruleTypeName));
} }
} }
@ -147,7 +147,7 @@ export class LicenseState {
} }
} }
public ensureLicenseForAlertType< public ensureLicenseForRuleType<
Params extends AlertTypeParams, Params extends AlertTypeParams,
ExtractedParams extends AlertTypeParams, ExtractedParams extends AlertTypeParams,
State extends AlertTypeState, State extends AlertTypeState,
@ -156,7 +156,7 @@ export class LicenseState {
ActionGroupIds extends string, ActionGroupIds extends string,
RecoveryActionGroupId extends string RecoveryActionGroupId extends string
>( >(
alertType: AlertType< ruleType: RuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -166,12 +166,12 @@ export class LicenseState {
RecoveryActionGroupId RecoveryActionGroupId
> >
) { ) {
this.notifyUsage(alertType.name, alertType.minimumLicenseRequired); this.notifyUsage(ruleType.name, ruleType.minimumLicenseRequired);
const check = this.getLicenseCheckForAlertType( const check = this.getLicenseCheckForRuleType(
alertType.id, ruleType.id,
alertType.name, ruleType.name,
alertType.minimumLicenseRequired ruleType.minimumLicenseRequired
); );
if (check.isValid) { if (check.isValid) {
@ -182,9 +182,9 @@ export class LicenseState {
throw new AlertTypeDisabledError( throw new AlertTypeDisabledError(
i18n.translate('xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage', { i18n.translate('xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage', {
defaultMessage: defaultMessage:
'Alert type {alertTypeId} is disabled because license information is not available at this time.', 'Rule type {ruleTypeId} is disabled because license information is not available at this time.',
values: { values: {
alertTypeId: alertType.id, ruleTypeId: ruleType.id,
}, },
}), }),
'license_unavailable' 'license_unavailable'
@ -193,8 +193,8 @@ export class LicenseState {
throw new AlertTypeDisabledError( throw new AlertTypeDisabledError(
i18n.translate('xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage', { i18n.translate('xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage', {
defaultMessage: defaultMessage:
'Alert type {alertTypeId} is disabled because your {licenseType} license has expired.', 'Rule type {ruleTypeId} is disabled because your {licenseType} license has expired.',
values: { alertTypeId: alertType.id, licenseType: this.license!.type }, values: { ruleTypeId: ruleType.id, licenseType: this.license!.type },
}), }),
'license_expired' 'license_expired'
); );
@ -202,10 +202,10 @@ export class LicenseState {
throw new AlertTypeDisabledError( throw new AlertTypeDisabledError(
i18n.translate('xpack.alerting.serverSideErrors.invalidLicenseErrorMessage', { i18n.translate('xpack.alerting.serverSideErrors.invalidLicenseErrorMessage', {
defaultMessage: defaultMessage:
'Alert {alertTypeId} is disabled because it requires a {licenseType} license. Go to License Management to view upgrade options.', 'Rule {ruleTypeId} is disabled because it requires a {licenseType} license. Go to License Management to view upgrade options.',
values: { values: {
alertTypeId: alertType.id, ruleTypeId: ruleType.id,
licenseType: capitalize(alertType.minimumLicenseRequired), licenseType: capitalize(ruleType.minimumLicenseRequired),
}, },
}), }),
'license_invalid' 'license_invalid'

View file

@ -10,14 +10,14 @@ import { AlertExecutionStatusErrorReasons } from '../types';
import { import {
executionStatusFromState, executionStatusFromState,
executionStatusFromError, executionStatusFromError,
alertExecutionStatusToRaw, ruleExecutionStatusToRaw,
alertExecutionStatusFromRaw, ruleExecutionStatusFromRaw,
} from './alert_execution_status'; } from './rule_execution_status';
import { ErrorWithReason } from './error_with_reason'; import { ErrorWithReason } from './error_with_reason';
const MockLogger = loggingSystemMock.create().get(); const MockLogger = loggingSystemMock.create().get();
describe('AlertExecutionStatus', () => { describe('RuleExecutionStatus', () => {
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
}); });
@ -71,14 +71,14 @@ describe('AlertExecutionStatus', () => {
}); });
}); });
describe('alertExecutionStatusToRaw()', () => { describe('ruleExecutionStatusToRaw()', () => {
const date = new Date('2020-09-03T16:26:58Z'); const date = new Date('2020-09-03T16:26:58Z');
const status = 'ok'; const status = 'ok';
const reason = AlertExecutionStatusErrorReasons.Decrypt; const reason = AlertExecutionStatusErrorReasons.Decrypt;
const error = { reason, message: 'wops' }; const error = { reason, message: 'wops' };
test('status without an error', () => { test('status without an error', () => {
expect(alertExecutionStatusToRaw({ lastExecutionDate: date, status })).toMatchInlineSnapshot(` expect(ruleExecutionStatusToRaw({ lastExecutionDate: date, status })).toMatchInlineSnapshot(`
Object { Object {
"error": null, "error": null,
"lastDuration": 0, "lastDuration": 0,
@ -89,7 +89,7 @@ describe('AlertExecutionStatus', () => {
}); });
test('status with an error', () => { test('status with an error', () => {
expect(alertExecutionStatusToRaw({ lastExecutionDate: date, status, error })) expect(ruleExecutionStatusToRaw({ lastExecutionDate: date, status, error }))
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
Object { Object {
"error": Object { "error": Object {
@ -104,7 +104,7 @@ describe('AlertExecutionStatus', () => {
}); });
test('status with a duration', () => { test('status with a duration', () => {
expect(alertExecutionStatusToRaw({ lastExecutionDate: date, status, lastDuration: 1234 })) expect(ruleExecutionStatusToRaw({ lastExecutionDate: date, status, lastDuration: 1234 }))
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
Object { Object {
"error": null, "error": null,
@ -116,41 +116,41 @@ describe('AlertExecutionStatus', () => {
}); });
}); });
describe('alertExecutionStatusFromRaw()', () => { describe('ruleExecutionStatusFromRaw()', () => {
const date = new Date('2020-09-03T16:26:58Z').toISOString(); const date = new Date('2020-09-03T16:26:58Z').toISOString();
const status = 'active'; const status = 'active';
const reason = AlertExecutionStatusErrorReasons.Execute; const reason = AlertExecutionStatusErrorReasons.Execute;
const error = { reason, message: 'wops' }; const error = { reason, message: 'wops' };
test('no input', () => { test('no input', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id'); const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id');
expect(result).toBe(undefined); expect(result).toBe(undefined);
}); });
test('undefined input', () => { test('undefined input', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', undefined); const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', undefined);
expect(result).toBe(undefined); expect(result).toBe(undefined);
}); });
test('null input', () => { test('null input', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', null); const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', null);
expect(result).toBe(undefined); expect(result).toBe(undefined);
}); });
test('invalid date', () => { test('invalid date', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', { const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
lastExecutionDate: 'an invalid date', lastExecutionDate: 'an invalid date',
})!; })!;
checkDateIsNearNow(result.lastExecutionDate); checkDateIsNearNow(result.lastExecutionDate);
expect(result.status).toBe('unknown'); expect(result.status).toBe('unknown');
expect(result.error).toBe(undefined); expect(result.error).toBe(undefined);
expect(MockLogger.debug).toBeCalledWith( expect(MockLogger.debug).toBeCalledWith(
'invalid alertExecutionStatus lastExecutionDate "an invalid date" in raw alert alert-id' 'invalid ruleExecutionStatus lastExecutionDate "an invalid date" in raw rule rule-id'
); );
}); });
test('valid date', () => { test('valid date', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', { const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
lastExecutionDate: date, lastExecutionDate: date,
}); });
expect(result).toMatchInlineSnapshot(` expect(result).toMatchInlineSnapshot(`
@ -162,7 +162,7 @@ describe('AlertExecutionStatus', () => {
}); });
test('valid status and date', () => { test('valid status and date', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', { const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
status, status,
lastExecutionDate: date, lastExecutionDate: date,
}); });
@ -175,7 +175,7 @@ describe('AlertExecutionStatus', () => {
}); });
test('valid status, date and error', () => { test('valid status, date and error', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', { const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
status, status,
lastExecutionDate: date, lastExecutionDate: date,
error, error,
@ -193,7 +193,7 @@ describe('AlertExecutionStatus', () => {
}); });
test('valid status, date and duration', () => { test('valid status, date and duration', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', { const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
status, status,
lastExecutionDate: date, lastExecutionDate: date,
lastDuration: 1234, lastDuration: 1234,
@ -208,7 +208,7 @@ describe('AlertExecutionStatus', () => {
}); });
test('valid status, date, error and duration', () => { test('valid status, date, error and duration', () => {
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', { const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
status, status,
lastExecutionDate: date, lastExecutionDate: date,
error, error,

View file

@ -6,16 +6,16 @@
*/ */
import { Logger } from 'src/core/server'; import { Logger } from 'src/core/server';
import { AlertTaskState, AlertExecutionStatus, RawAlertExecutionStatus } from '../types'; import { RuleTaskState, AlertExecutionStatus, RawRuleExecutionStatus } from '../types';
import { getReasonFromError } from './error_with_reason'; import { getReasonFromError } from './error_with_reason';
import { getEsErrorMessage } from './errors'; import { getEsErrorMessage } from './errors';
import { AlertExecutionStatuses } from '../../common'; import { AlertExecutionStatuses } from '../../common';
export function executionStatusFromState(state: AlertTaskState): AlertExecutionStatus { export function executionStatusFromState(state: RuleTaskState): AlertExecutionStatus {
const instanceIds = Object.keys(state.alertInstances ?? {}); const alertIds = Object.keys(state.alertInstances ?? {});
return { return {
lastExecutionDate: new Date(), lastExecutionDate: new Date(),
status: instanceIds.length === 0 ? 'ok' : 'active', status: alertIds.length === 0 ? 'ok' : 'active',
}; };
} }
@ -30,12 +30,12 @@ export function executionStatusFromError(error: Error): AlertExecutionStatus {
}; };
} }
export function alertExecutionStatusToRaw({ export function ruleExecutionStatusToRaw({
lastExecutionDate, lastExecutionDate,
lastDuration, lastDuration,
status, status,
error, error,
}: AlertExecutionStatus): RawAlertExecutionStatus { }: AlertExecutionStatus): RawRuleExecutionStatus {
return { return {
lastExecutionDate: lastExecutionDate.toISOString(), lastExecutionDate: lastExecutionDate.toISOString(),
lastDuration: lastDuration ?? 0, lastDuration: lastDuration ?? 0,
@ -45,19 +45,19 @@ export function alertExecutionStatusToRaw({
}; };
} }
export function alertExecutionStatusFromRaw( export function ruleExecutionStatusFromRaw(
logger: Logger, logger: Logger,
alertId: string, ruleId: string,
rawAlertExecutionStatus?: Partial<RawAlertExecutionStatus> | null | undefined rawRuleExecutionStatus?: Partial<RawRuleExecutionStatus> | null | undefined
): AlertExecutionStatus | undefined { ): AlertExecutionStatus | undefined {
if (!rawAlertExecutionStatus) return undefined; if (!rawRuleExecutionStatus) return undefined;
const { lastExecutionDate, lastDuration, status = 'unknown', error } = rawAlertExecutionStatus; const { lastExecutionDate, lastDuration, status = 'unknown', error } = rawRuleExecutionStatus;
let parsedDateMillis = lastExecutionDate ? Date.parse(lastExecutionDate) : Date.now(); let parsedDateMillis = lastExecutionDate ? Date.parse(lastExecutionDate) : Date.now();
if (isNaN(parsedDateMillis)) { if (isNaN(parsedDateMillis)) {
logger.debug( logger.debug(
`invalid alertExecutionStatus lastExecutionDate "${lastExecutionDate}" in raw alert ${alertId}` `invalid ruleExecutionStatus lastExecutionDate "${lastExecutionDate}" in raw rule ${ruleId}`
); );
parsedDateMillis = Date.now(); parsedDateMillis = Date.now();
} }
@ -78,7 +78,7 @@ export function alertExecutionStatusFromRaw(
return executionStatus; return executionStatus;
} }
export const getAlertExecutionStatusPending = (lastExecutionDate: string) => ({ export const getRuleExecutionStatusPending = (lastExecutionDate: string) => ({
status: 'pending' as AlertExecutionStatuses, status: 'pending' as AlertExecutionStatuses,
lastExecutionDate, lastExecutionDate,
error: null, error: null,

View file

@ -6,17 +6,17 @@
*/ */
import { schema } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema';
import { validateAlertTypeParams } from './validate_alert_type_params'; import { validateRuleTypeParams } from './validate_rule_type_params';
test('should return passed in params when validation not defined', () => { test('should return passed in params when validation not defined', () => {
const result = validateAlertTypeParams({ const result = validateRuleTypeParams({
foo: true, foo: true,
}); });
expect(result).toEqual({ foo: true }); expect(result).toEqual({ foo: true });
}); });
test('should validate and apply defaults when params is valid', () => { test('should validate and apply defaults when params is valid', () => {
const result = validateAlertTypeParams( const result = validateRuleTypeParams(
{ param1: 'value' }, { param1: 'value' },
schema.object({ schema.object({
param1: schema.string(), param1: schema.string(),
@ -31,7 +31,7 @@ test('should validate and apply defaults when params is valid', () => {
test('should validate and throw error when params is invalid', () => { test('should validate and throw error when params is invalid', () => {
expect(() => expect(() =>
validateAlertTypeParams( validateRuleTypeParams(
{}, {},
schema.object({ schema.object({
param1: schema.string(), param1: schema.string(),

View file

@ -8,7 +8,7 @@
import Boom from '@hapi/boom'; import Boom from '@hapi/boom';
import { AlertTypeParams, AlertTypeParamsValidator } from '../types'; import { AlertTypeParams, AlertTypeParamsValidator } from '../types';
export function validateAlertTypeParams<Params extends AlertTypeParams>( export function validateRuleTypeParams<Params extends AlertTypeParams>(
params: Record<string, unknown>, params: Record<string, unknown>,
validator?: AlertTypeParamsValidator<Params> validator?: AlertTypeParamsValidator<Params>
): Params { ): Params {

View file

@ -16,7 +16,7 @@ import { KibanaRequest } from 'kibana/server';
import { featuresPluginMock } from '../../features/server/mocks'; import { featuresPluginMock } from '../../features/server/mocks';
import { KibanaFeature } from '../../features/server'; import { KibanaFeature } from '../../features/server';
import { AlertsConfig } from './config'; import { AlertsConfig } from './config';
import { AlertType } from './types'; import { RuleType } from './types';
import { eventLogMock } from '../../event_log/server/mocks'; import { eventLogMock } from '../../event_log/server/mocks';
import { actionsMock } from '../../actions/server/mocks'; import { actionsMock } from '../../actions/server/mocks';
@ -99,7 +99,7 @@ describe('Alerting Plugin', () => {
describe('registerType()', () => { describe('registerType()', () => {
let setup: PluginSetupContract; let setup: PluginSetupContract;
const sampleAlertType: AlertType<never, never, never, never, never, 'default'> = { const sampleRuleType: RuleType<never, never, never, never, never, 'default'> = {
id: 'test', id: 'test',
name: 'test', name: 'test',
minimumLicenseRequired: 'basic', minimumLicenseRequired: 'basic',
@ -126,7 +126,7 @@ describe('Alerting Plugin', () => {
it('should throw error when license type is invalid', async () => { it('should throw error when license type is invalid', async () => {
expect(() => expect(() =>
setup.registerType({ setup.registerType({
...sampleAlertType, ...sampleRuleType,
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
minimumLicenseRequired: 'foo' as any, minimumLicenseRequired: 'foo' as any,
}) })
@ -135,52 +135,52 @@ describe('Alerting Plugin', () => {
it('should not throw when license type is gold', async () => { it('should not throw when license type is gold', async () => {
setup.registerType({ setup.registerType({
...sampleAlertType, ...sampleRuleType,
minimumLicenseRequired: 'gold', minimumLicenseRequired: 'gold',
}); });
}); });
it('should not throw when license type is basic', async () => { it('should not throw when license type is basic', async () => {
setup.registerType({ setup.registerType({
...sampleAlertType, ...sampleRuleType,
minimumLicenseRequired: 'basic', minimumLicenseRequired: 'basic',
}); });
}); });
it('should apply default config value for ruleTaskTimeout if no value is specified', async () => { it('should apply default config value for ruleTaskTimeout if no value is specified', async () => {
const ruleType = { const ruleType = {
...sampleAlertType, ...sampleRuleType,
minimumLicenseRequired: 'basic', minimumLicenseRequired: 'basic',
} as AlertType<never, never, never, never, never, 'default', never>; } as RuleType<never, never, never, never, never, 'default', never>;
await setup.registerType(ruleType); await setup.registerType(ruleType);
expect(ruleType.ruleTaskTimeout).toBe('5m'); expect(ruleType.ruleTaskTimeout).toBe('5m');
}); });
it('should apply value for ruleTaskTimeout if specified', async () => { it('should apply value for ruleTaskTimeout if specified', async () => {
const ruleType = { const ruleType = {
...sampleAlertType, ...sampleRuleType,
minimumLicenseRequired: 'basic', minimumLicenseRequired: 'basic',
ruleTaskTimeout: '20h', ruleTaskTimeout: '20h',
} as AlertType<never, never, never, never, never, 'default', never>; } as RuleType<never, never, never, never, never, 'default', never>;
await setup.registerType(ruleType); await setup.registerType(ruleType);
expect(ruleType.ruleTaskTimeout).toBe('20h'); expect(ruleType.ruleTaskTimeout).toBe('20h');
}); });
it('should apply default config value for cancelAlertsOnRuleTimeout if no value is specified', async () => { it('should apply default config value for cancelAlertsOnRuleTimeout if no value is specified', async () => {
const ruleType = { const ruleType = {
...sampleAlertType, ...sampleRuleType,
minimumLicenseRequired: 'basic', minimumLicenseRequired: 'basic',
} as AlertType<never, never, never, never, never, 'default', never>; } as RuleType<never, never, never, never, never, 'default', never>;
await setup.registerType(ruleType); await setup.registerType(ruleType);
expect(ruleType.cancelAlertsOnRuleTimeout).toBe(true); expect(ruleType.cancelAlertsOnRuleTimeout).toBe(true);
}); });
it('should apply value for cancelAlertsOnRuleTimeout if specified', async () => { it('should apply value for cancelAlertsOnRuleTimeout if specified', async () => {
const ruleType = { const ruleType = {
...sampleAlertType, ...sampleRuleType,
minimumLicenseRequired: 'basic', minimumLicenseRequired: 'basic',
cancelAlertsOnRuleTimeout: false, cancelAlertsOnRuleTimeout: false,
} as AlertType<never, never, never, never, never, 'default', never>; } as RuleType<never, never, never, never, never, 'default', never>;
await setup.registerType(ruleType); await setup.registerType(ruleType);
expect(ruleType.cancelAlertsOnRuleTimeout).toBe(false); expect(ruleType.cancelAlertsOnRuleTimeout).toBe(false);
}); });

View file

@ -46,7 +46,7 @@ import {
AlertInstanceContext, AlertInstanceContext,
AlertInstanceState, AlertInstanceState,
AlertsHealth, AlertsHealth,
AlertType, RuleType,
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
Services, Services,
@ -91,7 +91,7 @@ export interface PluginSetupContract {
ActionGroupIds extends string = never, ActionGroupIds extends string = never,
RecoveryActionGroupId extends string = never RecoveryActionGroupId extends string = never
>( >(
alertType: AlertType< ruleType: RuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -273,7 +273,7 @@ export class AlertingPlugin {
ActionGroupIds extends string = never, ActionGroupIds extends string = never,
RecoveryActionGroupId extends string = never RecoveryActionGroupId extends string = never
>( >(
alertType: AlertType< ruleType: RuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -283,15 +283,15 @@ export class AlertingPlugin {
RecoveryActionGroupId RecoveryActionGroupId
> >
) { ) {
if (!(alertType.minimumLicenseRequired in LICENSE_TYPE)) { if (!(ruleType.minimumLicenseRequired in LICENSE_TYPE)) {
throw new Error(`"${alertType.minimumLicenseRequired}" is not a valid license type`); throw new Error(`"${ruleType.minimumLicenseRequired}" is not a valid license type`);
} }
alertingConfig.then((config) => { alertingConfig.then((config) => {
alertType.ruleTaskTimeout = alertType.ruleTaskTimeout ?? config.defaultRuleTaskTimeout; ruleType.ruleTaskTimeout = ruleType.ruleTaskTimeout ?? config.defaultRuleTaskTimeout;
alertType.cancelAlertsOnRuleTimeout = ruleType.cancelAlertsOnRuleTimeout =
alertType.cancelAlertsOnRuleTimeout ?? config.cancelAlertsOnRuleTimeout; ruleType.cancelAlertsOnRuleTimeout ?? config.cancelAlertsOnRuleTimeout;
ruleTypeRegistry.register(alertType); ruleTypeRegistry.register(ruleType);
}); });
}, },
getSecurityHealth: async () => { getSecurityHealth: async () => {
@ -390,7 +390,7 @@ export class AlertingPlugin {
ruleTypeRegistry: this.ruleTypeRegistry!, ruleTypeRegistry: this.ruleTypeRegistry!,
kibanaBaseUrl: this.kibanaBaseUrl, kibanaBaseUrl: this.kibanaBaseUrl,
supportsEphemeralTasks: plugins.taskManager.supportsEphemeralTasks(), supportsEphemeralTasks: plugins.taskManager.supportsEphemeralTasks(),
maxEphemeralActionsPerAlert: config.maxEphemeralActionsPerAlert, maxEphemeralActionsPerRule: config.maxEphemeralActionsPerAlert,
cancelAlertsOnRuleTimeout: config.cancelAlertsOnRuleTimeout, cancelAlertsOnRuleTimeout: config.cancelAlertsOnRuleTimeout,
}); });
}); });

View file

@ -10,7 +10,7 @@ import { identity } from 'lodash';
import type { MethodKeysOf } from '@kbn/utility-types'; import type { MethodKeysOf } from '@kbn/utility-types';
import { httpServerMock } from '../../../../../src/core/server/mocks'; import { httpServerMock } from '../../../../../src/core/server/mocks';
import { rulesClientMock, RulesClientMock } from '../rules_client.mock'; import { rulesClientMock, RulesClientMock } from '../rules_client.mock';
import { AlertsHealth, AlertType } from '../../common'; import { AlertsHealth, RuleType } from '../../common';
import type { AlertingRequestHandlerContext } from '../types'; import type { AlertingRequestHandlerContext } from '../types';
export function mockHandlerArguments( export function mockHandlerArguments(
@ -21,7 +21,7 @@ export function mockHandlerArguments(
areApiKeysEnabled, areApiKeysEnabled,
}: { }: {
rulesClient?: RulesClientMock; rulesClient?: RulesClientMock;
listTypes?: AlertType[]; listTypes?: RuleType[];
getFrameworkHealth?: jest.MockInstance<Promise<AlertsHealth>, []> & getFrameworkHealth?: jest.MockInstance<Promise<AlertsHealth>, []> &
(() => Promise<AlertsHealth>); (() => Promise<AlertsHealth>);
areApiKeysEnabled?: () => Promise<boolean>; areApiKeysEnabled?: () => Promise<boolean>;

View file

@ -12,14 +12,14 @@ import { RewriteResponseCase, verifyAccessAndContext } from './lib';
import { import {
AlertingRequestHandlerContext, AlertingRequestHandlerContext,
INTERNAL_BASE_ALERTING_API_PATH, INTERNAL_BASE_ALERTING_API_PATH,
AlertTaskState, RuleTaskState,
} from '../types'; } from '../types';
const paramSchema = schema.object({ const paramSchema = schema.object({
id: schema.string(), id: schema.string(),
}); });
const rewriteBodyRes: RewriteResponseCase<AlertTaskState> = ({ const rewriteBodyRes: RewriteResponseCase<RuleTaskState> = ({
alertTypeState, alertTypeState,
alertInstances, alertInstances,
previousStartedAt, previousStartedAt,

View file

@ -7,7 +7,7 @@
import { TaskRunnerFactory } from './task_runner'; import { TaskRunnerFactory } from './task_runner';
import { RuleTypeRegistry, ConstructorOptions } from './rule_type_registry'; import { RuleTypeRegistry, ConstructorOptions } from './rule_type_registry';
import { ActionGroup, AlertType } from './types'; import { ActionGroup, RuleType } from './types';
import { taskManagerMock } from '../../task_manager/server/mocks'; import { taskManagerMock } from '../../task_manager/server/mocks';
import { ILicenseState } from './lib/license_state'; import { ILicenseState } from './lib/license_state';
import { licenseStateMock } from './lib/license_state.mock'; import { licenseStateMock } from './lib/license_state.mock';
@ -56,8 +56,8 @@ describe('has()', () => {
}); });
describe('register()', () => { describe('register()', () => {
test('throws if AlertType Id contains invalid characters', () => { test('throws if RuleType Id contains invalid characters', () => {
const alertType: AlertType<never, never, never, never, never, 'default'> = { const ruleType: RuleType<never, never, never, never, never, 'default'> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -76,21 +76,21 @@ describe('register()', () => {
const invalidCharacters = [' ', ':', '*', '*', '/']; const invalidCharacters = [' ', ':', '*', '*', '/'];
for (const char of invalidCharacters) { for (const char of invalidCharacters) {
expect(() => registry.register({ ...alertType, id: `${alertType.id}${char}` })).toThrowError( expect(() => registry.register({ ...ruleType, id: `${ruleType.id}${char}` })).toThrowError(
new Error(`expected AlertType Id not to include invalid character: ${char}`) new Error(`expected RuleType Id not to include invalid character: ${char}`)
); );
} }
const [first, second] = invalidCharacters; const [first, second] = invalidCharacters;
expect(() => expect(() =>
registry.register({ ...alertType, id: `${first}${alertType.id}${second}` }) registry.register({ ...ruleType, id: `${first}${ruleType.id}${second}` })
).toThrowError( ).toThrowError(
new Error(`expected AlertType Id not to include invalid characters: ${first}, ${second}`) new Error(`expected RuleType Id not to include invalid characters: ${first}, ${second}`)
); );
}); });
test('throws if AlertType Id isnt a string', () => { test('throws if RuleType Id isnt a string', () => {
const alertType: AlertType<never, never, never, never, never, 'default'> = { const ruleType: RuleType<never, never, never, never, never, 'default'> = {
id: 123 as unknown as string, id: 123 as unknown as string,
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -107,13 +107,13 @@ describe('register()', () => {
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
expect(() => registry.register(alertType)).toThrowError( expect(() => registry.register(ruleType)).toThrowError(
new Error(`expected value of type [string] but got [number]`) new Error(`expected value of type [string] but got [number]`)
); );
}); });
test('throws if AlertType ruleTaskTimeout is not a valid duration', () => { test('throws if RuleType ruleTaskTimeout is not a valid duration', () => {
const alertType: AlertType<never, never, never, never, never, 'default'> = { const ruleType: RuleType<never, never, never, never, never, 'default'> = {
id: '123', id: '123',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -131,7 +131,7 @@ describe('register()', () => {
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
expect(() => registry.register(alertType)).toThrowError( expect(() => registry.register(ruleType)).toThrowError(
new Error( new Error(
`Rule type \"123\" has invalid timeout: string is not a valid duration: 23 milisec.` `Rule type \"123\" has invalid timeout: string is not a valid duration: 23 milisec.`
) )
@ -139,7 +139,7 @@ describe('register()', () => {
}); });
test('throws if defaultScheduleInterval isnt valid', () => { test('throws if defaultScheduleInterval isnt valid', () => {
const alertType: AlertType<never, never, never, never, never, 'default'> = { const ruleType: RuleType<never, never, never, never, never, 'default'> = {
id: '123', id: '123',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -158,7 +158,7 @@ describe('register()', () => {
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
expect(() => registry.register(alertType)).toThrowError( expect(() => registry.register(ruleType)).toThrowError(
new Error( new Error(
`Rule type \"123\" has invalid default interval: string is not a valid duration: foobar.` `Rule type \"123\" has invalid default interval: string is not a valid duration: foobar.`
) )
@ -166,7 +166,7 @@ describe('register()', () => {
}); });
test('throws if minimumScheduleInterval isnt valid', () => { test('throws if minimumScheduleInterval isnt valid', () => {
const alertType: AlertType<never, never, never, never, never, 'default'> = { const ruleType: RuleType<never, never, never, never, never, 'default'> = {
id: '123', id: '123',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -184,7 +184,7 @@ describe('register()', () => {
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
expect(() => registry.register(alertType)).toThrowError( expect(() => registry.register(ruleType)).toThrowError(
new Error( new Error(
`Rule type \"123\" has invalid minimum interval: string is not a valid duration: foobar.` `Rule type \"123\" has invalid minimum interval: string is not a valid duration: foobar.`
) )
@ -192,7 +192,7 @@ describe('register()', () => {
}); });
test('throws if RuleType action groups contains reserved group id', () => { test('throws if RuleType action groups contains reserved group id', () => {
const alertType: AlertType<never, never, never, never, never, 'default' | 'NotReserved'> = { const ruleType: RuleType<never, never, never, never, never, 'default' | 'NotReserved'> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -217,15 +217,15 @@ describe('register()', () => {
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
expect(() => registry.register(alertType)).toThrowError( expect(() => registry.register(ruleType)).toThrowError(
new Error( new Error(
`Rule type [id="${alertType.id}"] cannot be registered. Action groups [recovered] are reserved by the framework.` `Rule type [id="${ruleType.id}"] cannot be registered. Action groups [recovered] are reserved by the framework.`
) )
); );
}); });
test('allows an AlertType to specify a custom recovery group', () => { test('allows an RuleType to specify a custom recovery group', () => {
const alertType: AlertType<never, never, never, never, never, 'default', 'backToAwesome'> = { const ruleType: RuleType<never, never, never, never, never, 'default', 'backToAwesome'> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -245,7 +245,7 @@ describe('register()', () => {
isExportable: true, isExportable: true,
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
registry.register(alertType); registry.register(ruleType);
expect(registry.get('test').actionGroups).toMatchInlineSnapshot(` expect(registry.get('test').actionGroups).toMatchInlineSnapshot(`
Array [ Array [
Object { Object {
@ -260,8 +260,8 @@ describe('register()', () => {
`); `);
}); });
test('allows an AlertType to specify a custom rule task timeout', () => { test('allows an RuleType to specify a custom rule task timeout', () => {
const alertType: AlertType<never, never, never, never, never, 'default', 'backToAwesome'> = { const ruleType: RuleType<never, never, never, never, never, 'default', 'backToAwesome'> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -278,12 +278,12 @@ describe('register()', () => {
isExportable: true, isExportable: true,
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
registry.register(alertType); registry.register(ruleType);
expect(registry.get('test').ruleTaskTimeout).toBe('13m'); expect(registry.get('test').ruleTaskTimeout).toBe('13m');
}); });
test('throws if the custom recovery group is contained in the AlertType action groups', () => { test('throws if the custom recovery group is contained in the RuleType action groups', () => {
const alertType: AlertType< const ruleType: RuleType<
never, never,
never, never,
never, never,
@ -316,15 +316,15 @@ describe('register()', () => {
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
expect(() => registry.register(alertType)).toThrowError( expect(() => registry.register(ruleType)).toThrowError(
new Error( new Error(
`Rule type [id="${alertType.id}"] cannot be registered. Action group [backToAwesome] cannot be used as both a recovery and an active action group.` `Rule type [id="${ruleType.id}"] cannot be registered. Action group [backToAwesome] cannot be used as both a recovery and an active action group.`
) )
); );
}); });
test('registers the executor with the task manager', () => { test('registers the executor with the task manager', () => {
const alertType: AlertType<never, never, never, never, never, 'default'> = { const ruleType: RuleType<never, never, never, never, never, 'default'> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -341,7 +341,7 @@ describe('register()', () => {
ruleTaskTimeout: '20m', ruleTaskTimeout: '20m',
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
registry.register(alertType); registry.register(ruleType);
expect(taskManager.registerTaskDefinitions).toHaveBeenCalledTimes(1); expect(taskManager.registerTaskDefinitions).toHaveBeenCalledTimes(1);
expect(taskManager.registerTaskDefinitions.mock.calls[0]).toMatchInlineSnapshot(` expect(taskManager.registerTaskDefinitions.mock.calls[0]).toMatchInlineSnapshot(`
Array [ Array [
@ -357,7 +357,7 @@ describe('register()', () => {
}); });
test('shallow clones the given rule type', () => { test('shallow clones the given rule type', () => {
const alertType: AlertType<never, never, never, never, never, 'default'> = { const ruleType: RuleType<never, never, never, never, never, 'default'> = {
id: 'test', id: 'test',
name: 'Test', name: 'Test',
actionGroups: [ actionGroups: [
@ -373,8 +373,8 @@ describe('register()', () => {
producer: 'alerts', producer: 'alerts',
}; };
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
registry.register(alertType); registry.register(ruleType);
alertType.name = 'Changed'; ruleType.name = 'Changed';
expect(registry.get('test').name).toEqual('Test'); expect(registry.get('test').name).toEqual('Test');
}); });
@ -433,8 +433,8 @@ describe('get()', () => {
executor: jest.fn(), executor: jest.fn(),
producer: 'alerts', producer: 'alerts',
}); });
const alertType = registry.get('test'); const ruleType = registry.get('test');
expect(alertType).toMatchInlineSnapshot(` expect(ruleType).toMatchInlineSnapshot(`
Object { Object {
"actionGroups": Array [ "actionGroups": Array [
Object { Object {
@ -539,12 +539,12 @@ describe('list()', () => {
test('should return action variables state and empty context', () => { test('should return action variables state and empty context', () => {
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
registry.register(alertTypeWithVariables('x', '', 's')); registry.register(ruleTypeWithVariables('x', '', 's'));
const alertType = registry.get('x'); const ruleType = registry.get('x');
expect(alertType.actionVariables).toBeTruthy(); expect(ruleType.actionVariables).toBeTruthy();
const context = alertType.actionVariables!.context; const context = ruleType.actionVariables!.context;
const state = alertType.actionVariables!.state; const state = ruleType.actionVariables!.state;
expect(context).toBeTruthy(); expect(context).toBeTruthy();
expect(context!.length).toBe(0); expect(context!.length).toBe(0);
@ -556,12 +556,12 @@ describe('list()', () => {
test('should return action variables context and empty state', () => { test('should return action variables context and empty state', () => {
const registry = new RuleTypeRegistry(ruleTypeRegistryParams); const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
registry.register(alertTypeWithVariables('x', 'c', '')); registry.register(ruleTypeWithVariables('x', 'c', ''));
const alertType = registry.get('x'); const ruleType = registry.get('x');
expect(alertType.actionVariables).toBeTruthy(); expect(ruleType.actionVariables).toBeTruthy();
const context = alertType.actionVariables!.context; const context = ruleType.actionVariables!.context;
const state = alertType.actionVariables!.state; const state = ruleType.actionVariables!.state;
expect(state).toBeTruthy(); expect(state).toBeTruthy();
expect(state!.length).toBe(0); expect(state!.length).toBe(0);
@ -597,11 +597,11 @@ describe('ensureRuleTypeEnabled', () => {
test('should call ensureLicenseForAlertType on the license state', async () => { test('should call ensureLicenseForAlertType on the license state', async () => {
ruleTypeRegistry.ensureRuleTypeEnabled('test'); ruleTypeRegistry.ensureRuleTypeEnabled('test');
expect(mockedLicenseState.ensureLicenseForAlertType).toHaveBeenCalled(); expect(mockedLicenseState.ensureLicenseForRuleType).toHaveBeenCalled();
}); });
test('should throw when ensureLicenseForAlertType throws', async () => { test('should throw when ensureLicenseForAlertType throws', async () => {
mockedLicenseState.ensureLicenseForAlertType.mockImplementation(() => { mockedLicenseState.ensureLicenseForRuleType.mockImplementation(() => {
throw new Error('Fail'); throw new Error('Fail');
}); });
expect(() => ruleTypeRegistry.ensureRuleTypeEnabled('test')).toThrowErrorMatchingInlineSnapshot( expect(() => ruleTypeRegistry.ensureRuleTypeEnabled('test')).toThrowErrorMatchingInlineSnapshot(
@ -610,12 +610,12 @@ describe('ensureRuleTypeEnabled', () => {
}); });
}); });
function alertTypeWithVariables<ActionGroupIds extends string>( function ruleTypeWithVariables<ActionGroupIds extends string>(
id: ActionGroupIds, id: ActionGroupIds,
context: string, context: string,
state: string state: string
): AlertType<never, never, never, never, never, ActionGroupIds> { ): RuleType<never, never, never, never, never, ActionGroupIds> {
const baseAlert: AlertType<never, never, never, never, never, ActionGroupIds> = { const baseAlert: RuleType<never, never, never, never, never, ActionGroupIds> = {
id, id,
name: `${id}-name`, name: `${id}-name`,
actionGroups: [], actionGroups: [],

View file

@ -14,7 +14,7 @@ import { LicensingPluginSetup } from '../../licensing/server';
import { RunContext, TaskManagerSetupContract } from '../../task_manager/server'; import { RunContext, TaskManagerSetupContract } from '../../task_manager/server';
import { TaskRunnerFactory } from './task_runner'; import { TaskRunnerFactory } from './task_runner';
import { import {
AlertType, RuleType,
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
AlertInstanceState, AlertInstanceState,
@ -28,7 +28,7 @@ import {
validateDurationSchema, validateDurationSchema,
} from '../common'; } from '../common';
import { ILicenseState } from './lib/license_state'; import { ILicenseState } from './lib/license_state';
import { getAlertTypeFeatureUsageName } from './lib/get_alert_type_feature_usage_name'; import { getRuleTypeFeatureUsageName } from './lib/get_rule_type_feature_usage_name';
export interface ConstructorOptions { export interface ConstructorOptions {
taskManager: TaskManagerSetupContract; taskManager: TaskManagerSetupContract;
@ -39,7 +39,7 @@ export interface ConstructorOptions {
export interface RegistryRuleType export interface RegistryRuleType
extends Pick< extends Pick<
UntypedNormalizedAlertType, UntypedNormalizedRuleType,
| 'name' | 'name'
| 'actionGroups' | 'actionGroups'
| 'recoveryActionGroup' | 'recoveryActionGroup'
@ -57,26 +57,26 @@ export interface RegistryRuleType
} }
/** /**
* AlertType IDs are used as part of the authorization strings used to * RuleType IDs are used as part of the authorization strings used to
* grant users privileged operations. There is a limited range of characters * grant users privileged operations. There is a limited range of characters
* we can use in these auth strings, so we apply these same limitations to * we can use in these auth strings, so we apply these same limitations to
* the AlertType Ids. * the RuleType Ids.
* If you wish to change this, please confer with the Kibana security team. * If you wish to change this, please confer with the Kibana security team.
*/ */
const alertIdSchema = schema.string({ const ruleTypeIdSchema = schema.string({
validate(value: string): string | void { validate(value: string): string | void {
if (typeof value !== 'string') { if (typeof value !== 'string') {
return `expected AlertType Id of type [string] but got [${typeDetect(value)}]`; return `expected RuleType Id of type [string] but got [${typeDetect(value)}]`;
} else if (!value.match(/^[a-zA-Z0-9_\-\.]*$/)) { } else if (!value.match(/^[a-zA-Z0-9_\-\.]*$/)) {
const invalid = value.match(/[^a-zA-Z0-9_\-\.]+/g)!; const invalid = value.match(/[^a-zA-Z0-9_\-\.]+/g)!;
return `expected AlertType Id not to include invalid character${ return `expected RuleType Id not to include invalid character${
invalid.length > 1 ? `s` : `` invalid.length > 1 ? `s` : ``
}: ${invalid?.join(`, `)}`; }: ${invalid?.join(`, `)}`;
} }
}, },
}); });
export type NormalizedAlertType< export type NormalizedRuleType<
Params extends AlertTypeParams, Params extends AlertTypeParams,
ExtractedParams extends AlertTypeParams, ExtractedParams extends AlertTypeParams,
State extends AlertTypeState, State extends AlertTypeState,
@ -87,7 +87,7 @@ export type NormalizedAlertType<
> = { > = {
actionGroups: Array<ActionGroup<ActionGroupIds | RecoveryActionGroupId>>; actionGroups: Array<ActionGroup<ActionGroupIds | RecoveryActionGroupId>>;
} & Omit< } & Omit<
AlertType< RuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -100,7 +100,7 @@ export type NormalizedAlertType<
> & > &
Pick< Pick<
Required< Required<
AlertType< RuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -113,7 +113,7 @@ export type NormalizedAlertType<
'recoveryActionGroup' 'recoveryActionGroup'
>; >;
export type UntypedNormalizedAlertType = NormalizedAlertType< export type UntypedNormalizedRuleType = NormalizedRuleType<
AlertTypeParams, AlertTypeParams,
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
@ -125,7 +125,7 @@ export type UntypedNormalizedAlertType = NormalizedAlertType<
export class RuleTypeRegistry { export class RuleTypeRegistry {
private readonly taskManager: TaskManagerSetupContract; private readonly taskManager: TaskManagerSetupContract;
private readonly ruleTypes: Map<string, UntypedNormalizedAlertType> = new Map(); private readonly ruleTypes: Map<string, UntypedNormalizedRuleType> = new Map();
private readonly taskRunnerFactory: TaskRunnerFactory; private readonly taskRunnerFactory: TaskRunnerFactory;
private readonly licenseState: ILicenseState; private readonly licenseState: ILicenseState;
private readonly licensing: LicensingPluginSetup; private readonly licensing: LicensingPluginSetup;
@ -142,7 +142,7 @@ export class RuleTypeRegistry {
} }
public ensureRuleTypeEnabled(id: string) { public ensureRuleTypeEnabled(id: string) {
this.licenseState.ensureLicenseForAlertType(this.get(id)); this.licenseState.ensureLicenseForRuleType(this.get(id));
} }
public register< public register<
@ -154,7 +154,7 @@ export class RuleTypeRegistry {
ActionGroupIds extends string, ActionGroupIds extends string,
RecoveryActionGroupId extends string RecoveryActionGroupId extends string
>( >(
alertType: AlertType< ruleType: RuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -164,44 +164,44 @@ export class RuleTypeRegistry {
RecoveryActionGroupId RecoveryActionGroupId
> >
) { ) {
if (this.has(alertType.id)) { if (this.has(ruleType.id)) {
throw new Error( throw new Error(
i18n.translate('xpack.alerting.ruleTypeRegistry.register.duplicateAlertTypeError', { i18n.translate('xpack.alerting.ruleTypeRegistry.register.duplicateRuleTypeError', {
defaultMessage: 'Rule type "{id}" is already registered.', defaultMessage: 'Rule type "{id}" is already registered.',
values: { values: {
id: alertType.id, id: ruleType.id,
}, },
}) })
); );
} }
// validate ruleTypeTimeout here // validate ruleTypeTimeout here
if (alertType.ruleTaskTimeout) { if (ruleType.ruleTaskTimeout) {
const invalidTimeout = validateDurationSchema(alertType.ruleTaskTimeout); const invalidTimeout = validateDurationSchema(ruleType.ruleTaskTimeout);
if (invalidTimeout) { if (invalidTimeout) {
throw new Error( throw new Error(
i18n.translate('xpack.alerting.ruleTypeRegistry.register.invalidTimeoutAlertTypeError', { i18n.translate('xpack.alerting.ruleTypeRegistry.register.invalidTimeoutRuleTypeError', {
defaultMessage: 'Rule type "{id}" has invalid timeout: {errorMessage}.', defaultMessage: 'Rule type "{id}" has invalid timeout: {errorMessage}.',
values: { values: {
id: alertType.id, id: ruleType.id,
errorMessage: invalidTimeout, errorMessage: invalidTimeout,
}, },
}) })
); );
} }
} }
alertType.actionVariables = normalizedActionVariables(alertType.actionVariables); ruleType.actionVariables = normalizedActionVariables(ruleType.actionVariables);
// validate defaultScheduleInterval here // validate defaultScheduleInterval here
if (alertType.defaultScheduleInterval) { if (ruleType.defaultScheduleInterval) {
const invalidDefaultTimeout = validateDurationSchema(alertType.defaultScheduleInterval); const invalidDefaultTimeout = validateDurationSchema(ruleType.defaultScheduleInterval);
if (invalidDefaultTimeout) { if (invalidDefaultTimeout) {
throw new Error( throw new Error(
i18n.translate( i18n.translate(
'xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutAlertTypeError', 'xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutRuleTypeError',
{ {
defaultMessage: 'Rule type "{id}" has invalid default interval: {errorMessage}.', defaultMessage: 'Rule type "{id}" has invalid default interval: {errorMessage}.',
values: { values: {
id: alertType.id, id: ruleType.id,
errorMessage: invalidDefaultTimeout, errorMessage: invalidDefaultTimeout,
}, },
} }
@ -211,16 +211,16 @@ export class RuleTypeRegistry {
} }
// validate minimumScheduleInterval here // validate minimumScheduleInterval here
if (alertType.minimumScheduleInterval) { if (ruleType.minimumScheduleInterval) {
const invalidMinimumTimeout = validateDurationSchema(alertType.minimumScheduleInterval); const invalidMinimumTimeout = validateDurationSchema(ruleType.minimumScheduleInterval);
if (invalidMinimumTimeout) { if (invalidMinimumTimeout) {
throw new Error( throw new Error(
i18n.translate( i18n.translate(
'xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutAlertTypeError', 'xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutRuleTypeError',
{ {
defaultMessage: 'Rule type "{id}" has invalid minimum interval: {errorMessage}.', defaultMessage: 'Rule type "{id}" has invalid minimum interval: {errorMessage}.',
values: { values: {
id: alertType.id, id: ruleType.id,
errorMessage: invalidMinimumTimeout, errorMessage: invalidMinimumTimeout,
}, },
} }
@ -229,7 +229,7 @@ export class RuleTypeRegistry {
} }
} }
const normalizedAlertType = augmentActionGroupsWithReserved< const normalizedRuleType = augmentActionGroupsWithReserved<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -237,17 +237,17 @@ export class RuleTypeRegistry {
InstanceContext, InstanceContext,
ActionGroupIds, ActionGroupIds,
RecoveryActionGroupId RecoveryActionGroupId
>(alertType); >(ruleType);
this.ruleTypes.set( this.ruleTypes.set(
alertIdSchema.validate(alertType.id), ruleTypeIdSchema.validate(ruleType.id),
/** stripping the typing is required in order to store the AlertTypes in a Map */ /** stripping the typing is required in order to store the RuleTypes in a Map */
normalizedAlertType as unknown as UntypedNormalizedAlertType normalizedRuleType as unknown as UntypedNormalizedRuleType
); );
this.taskManager.registerTaskDefinitions({ this.taskManager.registerTaskDefinitions({
[`alerting:${alertType.id}`]: { [`alerting:${ruleType.id}`]: {
title: alertType.name, title: ruleType.name,
timeout: alertType.ruleTaskTimeout, timeout: ruleType.ruleTaskTimeout,
createTaskRunner: (context: RunContext) => createTaskRunner: (context: RunContext) =>
this.taskRunnerFactory.create< this.taskRunnerFactory.create<
Params, Params,
@ -257,14 +257,14 @@ export class RuleTypeRegistry {
InstanceContext, InstanceContext,
ActionGroupIds, ActionGroupIds,
RecoveryActionGroupId | RecoveredActionGroupId RecoveryActionGroupId | RecoveredActionGroupId
>(normalizedAlertType, context), >(normalizedRuleType, context),
}, },
}); });
// No need to notify usage on basic alert types // No need to notify usage on basic alert types
if (alertType.minimumLicenseRequired !== 'basic') { if (ruleType.minimumLicenseRequired !== 'basic') {
this.licensing.featureUsage.register( this.licensing.featureUsage.register(
getAlertTypeFeatureUsageName(alertType.name), getRuleTypeFeatureUsageName(ruleType.name),
alertType.minimumLicenseRequired ruleType.minimumLicenseRequired
); );
} }
} }
@ -279,7 +279,7 @@ export class RuleTypeRegistry {
RecoveryActionGroupId extends string = string RecoveryActionGroupId extends string = string
>( >(
id: string id: string
): NormalizedAlertType< ): NormalizedRuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -290,7 +290,7 @@ export class RuleTypeRegistry {
> { > {
if (!this.has(id)) { if (!this.has(id)) {
throw Boom.badRequest( throw Boom.badRequest(
i18n.translate('xpack.alerting.ruleTypeRegistry.get.missingAlertTypeError', { i18n.translate('xpack.alerting.ruleTypeRegistry.get.missingRuleTypeError', {
defaultMessage: 'Rule type "{id}" is not registered.', defaultMessage: 'Rule type "{id}" is not registered.',
values: { values: {
id, id,
@ -299,11 +299,11 @@ export class RuleTypeRegistry {
); );
} }
/** /**
* When we store the AlertTypes in the Map we strip the typing. * When we store the RuleTypes in the Map we strip the typing.
* This means that returning a typed AlertType in `get` is an inherently * This means that returning a typed RuleType in `get` is an inherently
* unsafe operation. Down casting to `unknown` is the only way to achieve this. * unsafe operation. Down casting to `unknown` is the only way to achieve this.
*/ */
return this.ruleTypes.get(id)! as unknown as NormalizedAlertType< return this.ruleTypes.get(id)! as unknown as NormalizedRuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -332,7 +332,7 @@ export class RuleTypeRegistry {
minimumScheduleInterval, minimumScheduleInterval,
defaultScheduleInterval, defaultScheduleInterval,
}, },
]: [string, UntypedNormalizedAlertType]) => ({ ]: [string, UntypedNormalizedRuleType]) => ({
id, id,
name, name,
actionGroups, actionGroups,
@ -345,7 +345,7 @@ export class RuleTypeRegistry {
ruleTaskTimeout, ruleTaskTimeout,
minimumScheduleInterval, minimumScheduleInterval,
defaultScheduleInterval, defaultScheduleInterval,
enabledInLicense: !!this.licenseState.getLicenseCheckForAlertType( enabledInLicense: !!this.licenseState.getLicenseCheckForRuleType(
id, id,
name, name,
minimumLicenseRequired minimumLicenseRequired
@ -356,7 +356,7 @@ export class RuleTypeRegistry {
} }
} }
function normalizedActionVariables(actionVariables: AlertType['actionVariables']) { function normalizedActionVariables(actionVariables: RuleType['actionVariables']) {
return { return {
context: actionVariables?.context ?? [], context: actionVariables?.context ?? [],
state: actionVariables?.state ?? [], state: actionVariables?.state ?? [],
@ -373,7 +373,7 @@ function augmentActionGroupsWithReserved<
ActionGroupIds extends string, ActionGroupIds extends string,
RecoveryActionGroupId extends string RecoveryActionGroupId extends string
>( >(
alertType: AlertType< ruleType: RuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -382,7 +382,7 @@ function augmentActionGroupsWithReserved<
ActionGroupIds, ActionGroupIds,
RecoveryActionGroupId RecoveryActionGroupId
> >
): NormalizedAlertType< ): NormalizedRuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -391,8 +391,8 @@ function augmentActionGroupsWithReserved<
ActionGroupIds, ActionGroupIds,
RecoveredActionGroupId | RecoveryActionGroupId RecoveredActionGroupId | RecoveryActionGroupId
> { > {
const reservedActionGroups = getBuiltinActionGroups(alertType.recoveryActionGroup); const reservedActionGroups = getBuiltinActionGroups(ruleType.recoveryActionGroup);
const { id, actionGroups, recoveryActionGroup } = alertType; const { id, actionGroups, recoveryActionGroup } = ruleType;
const activeActionGroups = new Set<string>(actionGroups.map((item) => item.id)); const activeActionGroups = new Set<string>(actionGroups.map((item) => item.id));
const intersectingReservedActionGroups = intersection<string>( const intersectingReservedActionGroups = intersection<string>(
@ -427,7 +427,7 @@ function augmentActionGroupsWithReserved<
} }
return { return {
...alertType, ...ruleType,
actionGroups: [...actionGroups, ...reservedActionGroups], actionGroups: [...actionGroups, ...reservedActionGroups],
recoveryActionGroup: recoveryActionGroup ?? RecoveredActionGroup, recoveryActionGroup: recoveryActionGroup ?? RecoveredActionGroup,
}; };

View file

@ -24,27 +24,23 @@ import { ActionsClient, ActionsAuthorization } from '../../../actions/server';
import { import {
Alert, Alert,
PartialAlert, PartialAlert,
RawAlert, RawRule,
RuleTypeRegistry, RuleTypeRegistry,
AlertAction, AlertAction,
IntervalSchedule, IntervalSchedule,
SanitizedAlert, SanitizedAlert,
AlertTaskState, RuleTaskState,
AlertSummary, AlertSummary,
AlertExecutionStatusValues, AlertExecutionStatusValues,
AlertNotifyWhenType, AlertNotifyWhenType,
AlertTypeParams, AlertTypeParams,
ResolvedSanitizedRule, ResolvedSanitizedRule,
AlertWithLegacyId, AlertWithLegacyId,
SanitizedAlertWithLegacyId, SanitizedRuleWithLegacyId,
PartialAlertWithLegacyId, PartialAlertWithLegacyId,
RawAlertInstance, RawAlertInstance,
} from '../types'; } from '../types';
import { import { validateRuleTypeParams, ruleExecutionStatusFromRaw, getAlertNotifyWhenType } from '../lib';
validateAlertTypeParams,
alertExecutionStatusFromRaw,
getAlertNotifyWhenType,
} from '../lib';
import { import {
GrantAPIKeyResult as SecurityPluginGrantAPIKeyResult, GrantAPIKeyResult as SecurityPluginGrantAPIKeyResult,
InvalidateAPIKeyResult as SecurityPluginInvalidateAPIKeyResult, InvalidateAPIKeyResult as SecurityPluginInvalidateAPIKeyResult,
@ -52,7 +48,7 @@ import {
import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server'; import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server';
import { TaskManagerStartContract } from '../../../task_manager/server'; import { TaskManagerStartContract } from '../../../task_manager/server';
import { taskInstanceToAlertTaskInstance } from '../task_runner/alert_task_instance'; import { taskInstanceToAlertTaskInstance } from '../task_runner/alert_task_instance';
import { RegistryRuleType, UntypedNormalizedAlertType } from '../rule_type_registry'; import { RegistryRuleType, UntypedNormalizedRuleType } from '../rule_type_registry';
import { import {
AlertingAuthorization, AlertingAuthorization,
WriteOperations, WriteOperations,
@ -77,7 +73,7 @@ import { markApiKeyForInvalidation } from '../invalidate_pending_api_keys/mark_a
import { ruleAuditEvent, RuleAuditAction } from './audit_events'; import { ruleAuditEvent, RuleAuditAction } from './audit_events';
import { KueryNode, nodeBuilder } from '../../../../../src/plugins/data/common'; import { KueryNode, nodeBuilder } from '../../../../../src/plugins/data/common';
import { mapSortField } from './lib'; import { mapSortField } from './lib';
import { getAlertExecutionStatusPending } from '../lib/alert_execution_status'; import { getRuleExecutionStatusPending } from '../lib/rule_execution_status';
import { AlertInstance } from '../alert_instance'; import { AlertInstance } from '../alert_instance';
import { EVENT_LOG_ACTIONS } from '../plugin'; import { EVENT_LOG_ACTIONS } from '../plugin';
import { createAlertEventLogRecordObject } from '../lib/create_alert_event_log_record_object'; import { createAlertEventLogRecordObject } from '../lib/create_alert_event_log_record_object';
@ -316,10 +312,7 @@ export class RulesClient {
// Throws an error if alert type isn't registered // Throws an error if alert type isn't registered
const ruleType = this.ruleTypeRegistry.get(data.alertTypeId); const ruleType = this.ruleTypeRegistry.get(data.alertTypeId);
const validatedAlertTypeParams = validateAlertTypeParams( const validatedAlertTypeParams = validateRuleTypeParams(data.params, ruleType.validate?.params);
data.params,
ruleType.validate?.params
);
const username = await this.getUserName(); const username = await this.getUserName();
let createdAPIKey = null; let createdAPIKey = null;
@ -355,7 +348,7 @@ export class RulesClient {
const legacyId = Semver.lt(this.kibanaVersion, '8.0.0') ? id : null; const legacyId = Semver.lt(this.kibanaVersion, '8.0.0') ? id : null;
const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle); const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle);
const rawAlert: RawAlert = { const rawRule: RawRule = {
...data, ...data,
...this.apiKeyAsAlertAttributes(createdAPIKey, username), ...this.apiKeyAsAlertAttributes(createdAPIKey, username),
legacyId, legacyId,
@ -364,11 +357,11 @@ export class RulesClient {
updatedBy: username, updatedBy: username,
createdAt: new Date(createTime).toISOString(), createdAt: new Date(createTime).toISOString(),
updatedAt: new Date(createTime).toISOString(), updatedAt: new Date(createTime).toISOString(),
params: updatedParams as RawAlert['params'], params: updatedParams as RawRule['params'],
muteAll: false, muteAll: false,
mutedInstanceIds: [], mutedInstanceIds: [],
notifyWhen, notifyWhen,
executionStatus: getAlertExecutionStatusPending(new Date().toISOString()), executionStatus: getRuleExecutionStatusPending(new Date().toISOString()),
}; };
this.auditLogger?.log( this.auditLogger?.log(
@ -379,11 +372,11 @@ export class RulesClient {
}) })
); );
let createdAlert: SavedObject<RawAlert>; let createdAlert: SavedObject<RawRule>;
try { try {
createdAlert = await this.unsecuredSavedObjectsClient.create( createdAlert = await this.unsecuredSavedObjectsClient.create(
'alert', 'alert',
this.updateMeta(rawAlert), this.updateMeta(rawRule),
{ {
...options, ...options,
references, references,
@ -393,7 +386,7 @@ export class RulesClient {
} catch (e) { } catch (e) {
// Avoid unused API key // Avoid unused API key
markApiKeyForInvalidation( markApiKeyForInvalidation(
{ apiKey: rawAlert.apiKey }, { apiKey: rawRule.apiKey },
this.logger, this.logger,
this.unsecuredSavedObjectsClient this.unsecuredSavedObjectsClient
); );
@ -404,7 +397,7 @@ export class RulesClient {
try { try {
scheduledTask = await this.scheduleRule( scheduledTask = await this.scheduleRule(
createdAlert.id, createdAlert.id,
rawAlert.alertTypeId, rawRule.alertTypeId,
data.schedule, data.schedule,
true true
); );
@ -420,7 +413,7 @@ export class RulesClient {
} }
throw e; throw e;
} }
await this.unsecuredSavedObjectsClient.update<RawAlert>('alert', createdAlert.id, { await this.unsecuredSavedObjectsClient.update<RawRule>('alert', createdAlert.id, {
scheduledTaskId: scheduledTask.id, scheduledTaskId: scheduledTask.id,
}); });
createdAlert.attributes.scheduledTaskId = scheduledTask.id; createdAlert.attributes.scheduledTaskId = scheduledTask.id;
@ -439,8 +432,8 @@ export class RulesClient {
}: { }: {
id: string; id: string;
includeLegacyId?: boolean; includeLegacyId?: boolean;
}): Promise<SanitizedAlert<Params> | SanitizedAlertWithLegacyId<Params>> { }): Promise<SanitizedAlert<Params> | SanitizedRuleWithLegacyId<Params>> {
const result = await this.unsecuredSavedObjectsClient.get<RawAlert>('alert', id); const result = await this.unsecuredSavedObjectsClient.get<RawRule>('alert', id);
try { try {
await this.authorization.ensureAuthorized({ await this.authorization.ensureAuthorized({
ruleTypeId: result.attributes.alertTypeId, ruleTypeId: result.attributes.alertTypeId,
@ -481,7 +474,7 @@ export class RulesClient {
includeLegacyId?: boolean; includeLegacyId?: boolean;
}): Promise<ResolvedSanitizedRule<Params>> { }): Promise<ResolvedSanitizedRule<Params>> {
const { saved_object: result, ...resolveResponse } = const { saved_object: result, ...resolveResponse } =
await this.unsecuredSavedObjectsClient.resolve<RawAlert>('alert', id); await this.unsecuredSavedObjectsClient.resolve<RawRule>('alert', id);
try { try {
await this.authorization.ensureAuthorized({ await this.authorization.ensureAuthorized({
ruleTypeId: result.attributes.alertTypeId, ruleTypeId: result.attributes.alertTypeId,
@ -520,7 +513,7 @@ export class RulesClient {
}; };
} }
public async getAlertState({ id }: { id: string }): Promise<AlertTaskState | void> { public async getAlertState({ id }: { id: string }): Promise<RuleTaskState | void> {
const alert = await this.get({ id }); const alert = await this.get({ id });
await this.authorization.ensureAuthorized({ await this.authorization.ensureAuthorized({
ruleTypeId: alert.alertTypeId, ruleTypeId: alert.alertTypeId,
@ -539,7 +532,7 @@ export class RulesClient {
public async getAlertSummary({ id, dateStart }: GetAlertSummaryParams): Promise<AlertSummary> { public async getAlertSummary({ id, dateStart }: GetAlertSummaryParams): Promise<AlertSummary> {
this.logger.debug(`getAlertSummary(): getting alert ${id}`); this.logger.debug(`getAlertSummary(): getting alert ${id}`);
const rule = (await this.get({ id, includeLegacyId: true })) as SanitizedAlertWithLegacyId; const rule = (await this.get({ id, includeLegacyId: true })) as SanitizedRuleWithLegacyId;
await this.authorization.ensureAuthorized({ await this.authorization.ensureAuthorized({
ruleTypeId: rule.alertTypeId, ruleTypeId: rule.alertTypeId,
@ -612,7 +605,7 @@ export class RulesClient {
per_page: perPage, per_page: perPage,
total, total,
saved_objects: data, saved_objects: data,
} = await this.unsecuredSavedObjectsClient.find<RawAlert>({ } = await this.unsecuredSavedObjectsClient.find<RawRule>({
...options, ...options,
sortField: mapSortField(options.sortField), sortField: mapSortField(options.sortField),
filter: filter:
@ -646,7 +639,7 @@ export class RulesClient {
return this.getAlertFromRaw<Params>( return this.getAlertFromRaw<Params>(
id, id,
attributes.alertTypeId, attributes.alertTypeId,
fields ? (pick(attributes, fields) as RawAlert) : attributes, fields ? (pick(attributes, fields) as RawRule) : attributes,
references references
); );
}); });
@ -687,7 +680,7 @@ export class RulesClient {
throw error; throw error;
} }
const { filter: authorizationFilter } = authorizationTuple; const { filter: authorizationFilter } = authorizationTuple;
const resp = await this.unsecuredSavedObjectsClient.find<RawAlert, RuleAggregation>({ const resp = await this.unsecuredSavedObjectsClient.find<RawRule, RuleAggregation>({
...options, ...options,
filter: filter:
(authorizationFilter && filter (authorizationFilter && filter
@ -776,11 +769,11 @@ export class RulesClient {
private async deleteWithOCC({ id }: { id: string }) { private async deleteWithOCC({ id }: { id: string }) {
let taskIdToRemove: string | undefined | null; let taskIdToRemove: string | undefined | null;
let apiKeyToInvalidate: string | null = null; let apiKeyToInvalidate: string | null = null;
let attributes: RawAlert; let attributes: RawRule;
try { try {
const decryptedAlert = const decryptedAlert =
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, { await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
namespace: this.namespace, namespace: this.namespace,
}); });
apiKeyToInvalidate = decryptedAlert.attributes.apiKey; apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
@ -792,7 +785,7 @@ export class RulesClient {
`delete(): Failed to load API key to invalidate on alert ${id}: ${e.message}` `delete(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
); );
// Still attempt to load the scheduledTaskId using SOC // Still attempt to load the scheduledTaskId using SOC
const alert = await this.unsecuredSavedObjectsClient.get<RawAlert>('alert', id); const alert = await this.unsecuredSavedObjectsClient.get<RawRule>('alert', id);
taskIdToRemove = alert.attributes.scheduledTaskId; taskIdToRemove = alert.attributes.scheduledTaskId;
attributes = alert.attributes; attributes = alert.attributes;
} }
@ -854,20 +847,23 @@ export class RulesClient {
id, id,
data, data,
}: UpdateOptions<Params>): Promise<PartialAlert<Params>> { }: UpdateOptions<Params>): Promise<PartialAlert<Params>> {
let alertSavedObject: SavedObject<RawAlert>; let alertSavedObject: SavedObject<RawRule>;
try { try {
alertSavedObject = alertSavedObject = await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>(
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, { 'alert',
id,
{
namespace: this.namespace, namespace: this.namespace,
}); }
);
} catch (e) { } catch (e) {
// We'll skip invalidating the API key since we failed to load the decrypted saved object // We'll skip invalidating the API key since we failed to load the decrypted saved object
this.logger.error( this.logger.error(
`update(): Failed to load API key to invalidate on alert ${id}: ${e.message}` `update(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
); );
// Still attempt to load the object using SOC // Still attempt to load the object using SOC
alertSavedObject = await this.unsecuredSavedObjectsClient.get<RawAlert>('alert', id); alertSavedObject = await this.unsecuredSavedObjectsClient.get<RawRule>('alert', id);
} }
try { try {
@ -934,15 +930,12 @@ export class RulesClient {
private async updateAlert<Params extends AlertTypeParams>( private async updateAlert<Params extends AlertTypeParams>(
{ id, data }: UpdateOptions<Params>, { id, data }: UpdateOptions<Params>,
{ attributes, version }: SavedObject<RawAlert> { attributes, version }: SavedObject<RawRule>
): Promise<PartialAlert<Params>> { ): Promise<PartialAlert<Params>> {
const ruleType = this.ruleTypeRegistry.get(attributes.alertTypeId); const ruleType = this.ruleTypeRegistry.get(attributes.alertTypeId);
// Validate // Validate
const validatedAlertTypeParams = validateAlertTypeParams( const validatedAlertTypeParams = validateRuleTypeParams(data.params, ruleType.validate?.params);
data.params,
ruleType.validate?.params
);
await this.validateActions(ruleType, data.actions); await this.validateActions(ruleType, data.actions);
// Validate intervals, if configured // Validate intervals, if configured
@ -977,19 +970,19 @@ export class RulesClient {
const apiKeyAttributes = this.apiKeyAsAlertAttributes(createdAPIKey, username); const apiKeyAttributes = this.apiKeyAsAlertAttributes(createdAPIKey, username);
const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle); const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle);
let updatedObject: SavedObject<RawAlert>; let updatedObject: SavedObject<RawRule>;
const createAttributes = this.updateMeta({ const createAttributes = this.updateMeta({
...attributes, ...attributes,
...data, ...data,
...apiKeyAttributes, ...apiKeyAttributes,
params: updatedParams as RawAlert['params'], params: updatedParams as RawRule['params'],
actions, actions,
notifyWhen, notifyWhen,
updatedBy: username, updatedBy: username,
updatedAt: new Date().toISOString(), updatedAt: new Date().toISOString(),
}); });
try { try {
updatedObject = await this.unsecuredSavedObjectsClient.create<RawAlert>( updatedObject = await this.unsecuredSavedObjectsClient.create<RawRule>(
'alert', 'alert',
createAttributes, createAttributes,
{ {
@ -1020,7 +1013,7 @@ export class RulesClient {
private apiKeyAsAlertAttributes( private apiKeyAsAlertAttributes(
apiKey: CreateAPIKeyResult | null, apiKey: CreateAPIKeyResult | null,
username: string | null username: string | null
): Pick<RawAlert, 'apiKey' | 'apiKeyOwner'> { ): Pick<RawRule, 'apiKey' | 'apiKeyOwner'> {
return apiKey && apiKey.apiKeysEnabled return apiKey && apiKey.apiKeysEnabled
? { ? {
apiKeyOwner: username, apiKeyOwner: username,
@ -1042,12 +1035,12 @@ export class RulesClient {
private async updateApiKeyWithOCC({ id }: { id: string }) { private async updateApiKeyWithOCC({ id }: { id: string }) {
let apiKeyToInvalidate: string | null = null; let apiKeyToInvalidate: string | null = null;
let attributes: RawAlert; let attributes: RawRule;
let version: string | undefined; let version: string | undefined;
try { try {
const decryptedAlert = const decryptedAlert =
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, { await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
namespace: this.namespace, namespace: this.namespace,
}); });
apiKeyToInvalidate = decryptedAlert.attributes.apiKey; apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
@ -1059,7 +1052,7 @@ export class RulesClient {
`updateApiKey(): Failed to load API key to invalidate on alert ${id}: ${e.message}` `updateApiKey(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
); );
// Still attempt to load the attributes and version using SOC // Still attempt to load the attributes and version using SOC
const alert = await this.unsecuredSavedObjectsClient.get<RawAlert>('alert', id); const alert = await this.unsecuredSavedObjectsClient.get<RawRule>('alert', id);
attributes = alert.attributes; attributes = alert.attributes;
version = alert.version; version = alert.version;
} }
@ -1146,12 +1139,12 @@ export class RulesClient {
private async enableWithOCC({ id }: { id: string }) { private async enableWithOCC({ id }: { id: string }) {
let apiKeyToInvalidate: string | null = null; let apiKeyToInvalidate: string | null = null;
let attributes: RawAlert; let attributes: RawRule;
let version: string | undefined; let version: string | undefined;
try { try {
const decryptedAlert = const decryptedAlert =
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, { await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
namespace: this.namespace, namespace: this.namespace,
}); });
apiKeyToInvalidate = decryptedAlert.attributes.apiKey; apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
@ -1163,7 +1156,7 @@ export class RulesClient {
`enable(): Failed to load API key to invalidate on alert ${id}: ${e.message}` `enable(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
); );
// Still attempt to load the attributes and version using SOC // Still attempt to load the attributes and version using SOC
const alert = await this.unsecuredSavedObjectsClient.get<RawAlert>('alert', id); const alert = await this.unsecuredSavedObjectsClient.get<RawRule>('alert', id);
attributes = alert.attributes; attributes = alert.attributes;
version = alert.version; version = alert.version;
} }
@ -1265,12 +1258,12 @@ export class RulesClient {
private async disableWithOCC({ id }: { id: string }) { private async disableWithOCC({ id }: { id: string }) {
let apiKeyToInvalidate: string | null = null; let apiKeyToInvalidate: string | null = null;
let attributes: RawAlert; let attributes: RawRule;
let version: string | undefined; let version: string | undefined;
try { try {
const decryptedAlert = const decryptedAlert =
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, { await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
namespace: this.namespace, namespace: this.namespace,
}); });
apiKeyToInvalidate = decryptedAlert.attributes.apiKey; apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
@ -1282,7 +1275,7 @@ export class RulesClient {
`disable(): Failed to load API key to invalidate on alert ${id}: ${e.message}` `disable(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
); );
// Still attempt to load the attributes and version using SOC // Still attempt to load the attributes and version using SOC
const alert = await this.unsecuredSavedObjectsClient.get<RawAlert>('alert', id); const alert = await this.unsecuredSavedObjectsClient.get<RawRule>('alert', id);
attributes = alert.attributes; attributes = alert.attributes;
version = alert.version; version = alert.version;
} }
@ -1403,7 +1396,7 @@ export class RulesClient {
} }
private async muteAllWithOCC({ id }: { id: string }) { private async muteAllWithOCC({ id }: { id: string }) {
const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawAlert>( const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawRule>(
'alert', 'alert',
id id
); );
@ -1465,7 +1458,7 @@ export class RulesClient {
} }
private async unmuteAllWithOCC({ id }: { id: string }) { private async unmuteAllWithOCC({ id }: { id: string }) {
const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawAlert>( const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawRule>(
'alert', 'alert',
id id
); );
@ -1633,7 +1626,7 @@ export class RulesClient {
const mutedInstanceIds = attributes.mutedInstanceIds || []; const mutedInstanceIds = attributes.mutedInstanceIds || [];
if (!attributes.muteAll && mutedInstanceIds.includes(alertInstanceId)) { if (!attributes.muteAll && mutedInstanceIds.includes(alertInstanceId)) {
await this.unsecuredSavedObjectsClient.update<RawAlert>( await this.unsecuredSavedObjectsClient.update<RawRule>(
'alert', 'alert',
alertId, alertId,
this.updateMeta({ this.updateMeta({
@ -1691,7 +1684,7 @@ export class RulesClient {
private injectReferencesIntoActions( private injectReferencesIntoActions(
alertId: string, alertId: string,
actions: RawAlert['actions'], actions: RawRule['actions'],
references: SavedObjectReference[] references: SavedObjectReference[]
) { ) {
return actions.map((action) => { return actions.map((action) => {
@ -1716,18 +1709,18 @@ export class RulesClient {
private getAlertFromRaw<Params extends AlertTypeParams>( private getAlertFromRaw<Params extends AlertTypeParams>(
id: string, id: string,
ruleTypeId: string, ruleTypeId: string,
rawAlert: RawAlert, rawRule: RawRule,
references: SavedObjectReference[] | undefined, references: SavedObjectReference[] | undefined,
includeLegacyId: boolean = false includeLegacyId: boolean = false
): Alert | AlertWithLegacyId { ): Alert | AlertWithLegacyId {
const ruleType = this.ruleTypeRegistry.get(ruleTypeId); const ruleType = this.ruleTypeRegistry.get(ruleTypeId);
// In order to support the partial update API of Saved Objects we have to support // In order to support the partial update API of Saved Objects we have to support
// partial updates of an Alert, but when we receive an actual RawAlert, it is safe // partial updates of an Alert, but when we receive an actual RawRule, it is safe
// to cast the result to an Alert // to cast the result to an Alert
const res = this.getPartialAlertFromRaw<Params>( const res = this.getPartialAlertFromRaw<Params>(
id, id,
ruleType, ruleType,
rawAlert, rawRule,
references, references,
includeLegacyId includeLegacyId
); );
@ -1741,7 +1734,7 @@ export class RulesClient {
private getPartialAlertFromRaw<Params extends AlertTypeParams>( private getPartialAlertFromRaw<Params extends AlertTypeParams>(
id: string, id: string,
ruleType: UntypedNormalizedAlertType, ruleType: UntypedNormalizedRuleType,
{ {
createdAt, createdAt,
updatedAt, updatedAt,
@ -1753,15 +1746,15 @@ export class RulesClient {
executionStatus, executionStatus,
schedule, schedule,
actions, actions,
...partialRawAlert ...partialRawRule
}: Partial<RawAlert>, }: Partial<RawRule>,
references: SavedObjectReference[] | undefined, references: SavedObjectReference[] | undefined,
includeLegacyId: boolean = false includeLegacyId: boolean = false
): PartialAlert<Params> | PartialAlertWithLegacyId<Params> { ): PartialAlert<Params> | PartialAlertWithLegacyId<Params> {
const rule = { const rule = {
id, id,
notifyWhen, notifyWhen,
...partialRawAlert, ...partialRawRule,
// we currently only support the Interval Schedule type // we currently only support the Interval Schedule type
// Once we support additional types, this type signature will likely change // Once we support additional types, this type signature will likely change
schedule: schedule as IntervalSchedule, schedule: schedule as IntervalSchedule,
@ -1771,7 +1764,7 @@ export class RulesClient {
...(createdAt ? { createdAt: new Date(createdAt) } : {}), ...(createdAt ? { createdAt: new Date(createdAt) } : {}),
...(scheduledTaskId ? { scheduledTaskId } : {}), ...(scheduledTaskId ? { scheduledTaskId } : {}),
...(executionStatus ...(executionStatus
? { executionStatus: alertExecutionStatusFromRaw(this.logger, id, executionStatus) } ? { executionStatus: ruleExecutionStatusFromRaw(this.logger, id, executionStatus) }
: {}), : {}),
}; };
return includeLegacyId return includeLegacyId
@ -1780,7 +1773,7 @@ export class RulesClient {
} }
private async validateActions( private async validateActions(
alertType: UntypedNormalizedAlertType, alertType: UntypedNormalizedRuleType,
actions: NormalizedAlertAction[] actions: NormalizedAlertAction[]
): Promise<void> { ): Promise<void> {
if (actions.length === 0) { if (actions.length === 0) {
@ -1831,11 +1824,11 @@ export class RulesClient {
Params extends AlertTypeParams, Params extends AlertTypeParams,
ExtractedParams extends AlertTypeParams ExtractedParams extends AlertTypeParams
>( >(
ruleType: UntypedNormalizedAlertType, ruleType: UntypedNormalizedRuleType,
ruleActions: NormalizedAlertAction[], ruleActions: NormalizedAlertAction[],
ruleParams: Params ruleParams: Params
): Promise<{ ): Promise<{
actions: RawAlert['actions']; actions: RawRule['actions'];
params: ExtractedParams; params: ExtractedParams;
references: SavedObjectReference[]; references: SavedObjectReference[];
}> { }> {
@ -1868,7 +1861,7 @@ export class RulesClient {
ExtractedParams extends AlertTypeParams ExtractedParams extends AlertTypeParams
>( >(
ruleId: string, ruleId: string,
ruleType: UntypedNormalizedAlertType, ruleType: UntypedNormalizedRuleType,
ruleParams: SavedObjectAttributes | undefined, ruleParams: SavedObjectAttributes | undefined,
references: SavedObjectReference[] references: SavedObjectReference[]
): Params { ): Params {
@ -1896,9 +1889,9 @@ export class RulesClient {
private async denormalizeActions( private async denormalizeActions(
alertActions: NormalizedAlertAction[] alertActions: NormalizedAlertAction[]
): Promise<{ actions: RawAlert['actions']; references: SavedObjectReference[] }> { ): Promise<{ actions: RawRule['actions']; references: SavedObjectReference[] }> {
const references: SavedObjectReference[] = []; const references: SavedObjectReference[] = [];
const actions: RawAlert['actions'] = []; const actions: RawRule['actions'] = [];
if (alertActions.length) { if (alertActions.length) {
const actionsClient = await this.getActionsClient(); const actionsClient = await this.getActionsClient();
const actionIds = [...new Set(alertActions.map((alertAction) => alertAction.id))]; const actionIds = [...new Set(alertActions.map((alertAction) => alertAction.id))];
@ -1953,7 +1946,7 @@ export class RulesClient {
return truncate(`Alerting: ${alertTypeId}/${trim(alertName)}`, { length: 256 }); return truncate(`Alerting: ${alertTypeId}/${trim(alertName)}`, { length: 256 });
} }
private updateMeta<T extends Partial<RawAlert>>(alertAttributes: T): T { private updateMeta<T extends Partial<RawRule>>(alertAttributes: T): T {
if (alertAttributes.hasOwnProperty('apiKey') || alertAttributes.hasOwnProperty('apiKeyOwner')) { if (alertAttributes.hasOwnProperty('apiKey') || alertAttributes.hasOwnProperty('apiKeyOwner')) {
alertAttributes.meta = alertAttributes.meta ?? {}; alertAttributes.meta = alertAttributes.meta ?? {};
alertAttributes.meta.versionApiKeyLastmodified = this.kibanaVersion; alertAttributes.meta.versionApiKeyLastmodified = this.kibanaVersion;

View file

@ -19,7 +19,7 @@ import { eventLogClientMock } from '../../../../event_log/server/mocks';
import { QueryEventsBySavedObjectResult } from '../../../../event_log/server'; import { QueryEventsBySavedObjectResult } from '../../../../event_log/server';
import { SavedObject } from 'kibana/server'; import { SavedObject } from 'kibana/server';
import { EventsFactory } from '../../lib/alert_summary_from_event_log.test'; import { EventsFactory } from '../../lib/alert_summary_from_event_log.test';
import { RawAlert } from '../../types'; import { RawRule } from '../../types';
import { getBeforeSetup, mockedDateString, setGlobalDate } from './lib'; import { getBeforeSetup, mockedDateString, setGlobalDate } from './lib';
const taskManager = taskManagerMock.createStart(); const taskManager = taskManagerMock.createStart();
@ -64,7 +64,7 @@ const AlertSummaryFindEventsResult: QueryEventsBySavedObjectResult = {
const RuleIntervalSeconds = 1; const RuleIntervalSeconds = 1;
const BaseRuleSavedObject: SavedObject<RawAlert> = { const BaseRuleSavedObject: SavedObject<RawRule> = {
id: '1', id: '1',
type: 'alert', type: 'alert',
attributes: { attributes: {
@ -96,7 +96,7 @@ const BaseRuleSavedObject: SavedObject<RawAlert> = {
references: [], references: [],
}; };
function getRuleSavedObject(attributes: Partial<RawAlert> = {}): SavedObject<RawAlert> { function getRuleSavedObject(attributes: Partial<RawRule> = {}): SavedObject<RawRule> {
return { return {
...BaseRuleSavedObject, ...BaseRuleSavedObject,
attributes: { ...BaseRuleSavedObject.attributes, ...attributes }, attributes: { ...BaseRuleSavedObject.attributes, ...attributes },

View file

@ -12,7 +12,7 @@ import {
} from 'kibana/server'; } from 'kibana/server';
import { AlertTypeParams } from '../../index'; import { AlertTypeParams } from '../../index';
import { Query } from '../../../../../../src/plugins/data/common/query'; import { Query } from '../../../../../../src/plugins/data/common/query';
import { RawAlert } from '../../types'; import { RawRule } from '../../types';
// These definitions are dupes of the SO-types in stack_alerts/geo_containment // These definitions are dupes of the SO-types in stack_alerts/geo_containment
// There are not exported to avoid deep imports from stack_alerts plugins into here // There are not exported to avoid deep imports from stack_alerts plugins into here
@ -69,8 +69,8 @@ export function extractEntityAndBoundaryReferences(params: GeoContainmentParams)
} }
export function extractRefsFromGeoContainmentAlert( export function extractRefsFromGeoContainmentAlert(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
if (doc.attributes.alertTypeId !== GEO_CONTAINMENT_ID) { if (doc.attributes.alertTypeId !== GEO_CONTAINMENT_ID) {
return doc; return doc;
} }

View file

@ -6,7 +6,7 @@
*/ */
import { SavedObject } from 'kibana/server'; import { SavedObject } from 'kibana/server';
import { RawAlert } from '../types'; import { RawRule } from '../types';
import { getImportWarnings } from './get_import_warnings'; import { getImportWarnings } from './get_import_warnings';
describe('getImportWarnings', () => { describe('getImportWarnings', () => {
@ -71,13 +71,13 @@ describe('getImportWarnings', () => {
references: [], references: [],
}, },
]; ];
const warnings = getImportWarnings(savedObjectRules as unknown as Array<SavedObject<RawAlert>>); const warnings = getImportWarnings(savedObjectRules as unknown as Array<SavedObject<RawRule>>);
expect(warnings[0].message).toBe('2 rules must be enabled after the import.'); expect(warnings[0].message).toBe('2 rules must be enabled after the import.');
}); });
it('return no warning messages if no rules were imported', () => { it('return no warning messages if no rules were imported', () => {
const savedObjectRules = [] as Array<SavedObject<RawAlert>>; const savedObjectRules = [] as Array<SavedObject<RawRule>>;
const warnings = getImportWarnings(savedObjectRules as unknown as Array<SavedObject<RawAlert>>); const warnings = getImportWarnings(savedObjectRules as unknown as Array<SavedObject<RawRule>>);
expect(warnings.length).toBe(0); expect(warnings.length).toBe(0);
}); });
}); });

View file

@ -16,7 +16,7 @@ import mappings from './mappings.json';
import { getMigrations } from './migrations'; import { getMigrations } from './migrations';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server'; import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
import { transformRulesForExport } from './transform_rule_for_export'; import { transformRulesForExport } from './transform_rule_for_export';
import { RawAlert } from '../types'; import { RawRule } from '../types';
import { getImportWarnings } from './get_import_warnings'; import { getImportWarnings } from './get_import_warnings';
import { isRuleExportable } from './is_rule_exportable'; import { isRuleExportable } from './is_rule_exportable';
import { RuleTypeRegistry } from '../rule_type_registry'; import { RuleTypeRegistry } from '../rule_type_registry';
@ -60,7 +60,7 @@ export function setupSavedObjects(
management: { management: {
displayName: 'rule', displayName: 'rule',
importableAndExportable: true, importableAndExportable: true,
getTitle(ruleSavedObject: SavedObject<RawAlert>) { getTitle(ruleSavedObject: SavedObject<RawRule>) {
return `Rule: [${ruleSavedObject.attributes.name}]`; return `Rule: [${ruleSavedObject.attributes.name}]`;
}, },
onImport(ruleSavedObjects) { onImport(ruleSavedObjects) {
@ -68,13 +68,13 @@ export function setupSavedObjects(
warnings: getImportWarnings(ruleSavedObjects), warnings: getImportWarnings(ruleSavedObjects),
}; };
}, },
onExport<RawAlert>( onExport<RawRule>(
context: SavedObjectsExportTransformContext, context: SavedObjectsExportTransformContext,
objects: Array<SavedObject<RawAlert>> objects: Array<SavedObject<RawRule>>
) { ) {
return transformRulesForExport(objects); return transformRulesForExport(objects);
}, },
isExportable<RawAlert>(ruleSavedObject: SavedObject<RawAlert>) { isExportable<RawRule>(ruleSavedObject: SavedObject<RawRule>) {
return isRuleExportable(ruleSavedObject, ruleTypeRegistry, logger); return isRuleExportable(ruleSavedObject, ruleTypeRegistry, logger);
}, },
}, },

View file

@ -6,7 +6,7 @@
*/ */
import { Logger, SavedObject } from 'kibana/server'; import { Logger, SavedObject } from 'kibana/server';
import { RawAlert } from '../types'; import { RawRule } from '../types';
import { RuleTypeRegistry } from '../rule_type_registry'; import { RuleTypeRegistry } from '../rule_type_registry';
export function isRuleExportable( export function isRuleExportable(
@ -14,7 +14,7 @@ export function isRuleExportable(
ruleTypeRegistry: RuleTypeRegistry, ruleTypeRegistry: RuleTypeRegistry,
logger: Logger logger: Logger
): boolean { ): boolean {
const ruleSO = rule as SavedObject<RawAlert>; const ruleSO = rule as SavedObject<RawRule>;
try { try {
const ruleType = ruleTypeRegistry.get(ruleSO.attributes.alertTypeId); const ruleType = ruleTypeRegistry.get(ruleSO.attributes.alertTypeId);
if (!ruleType.isExportable) { if (!ruleType.isExportable) {

View file

@ -7,7 +7,7 @@
import uuid from 'uuid'; import uuid from 'uuid';
import { getMigrations, isAnyActionSupportIncidents } from './migrations'; import { getMigrations, isAnyActionSupportIncidents } from './migrations';
import { RawAlert } from '../types'; import { RawRule } from '../types';
import { SavedObjectUnsanitizedDoc } from 'kibana/server'; import { SavedObjectUnsanitizedDoc } from 'kibana/server';
import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks'; import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks';
import { migrationMocks } from 'src/core/server/mocks'; import { migrationMocks } from 'src/core/server/mocks';
@ -512,7 +512,7 @@ describe('successful migrations', () => {
(actionTypeId) => { (actionTypeId) => {
const doc = { const doc = {
attributes: { actions: [{ actionTypeId }, { actionTypeId: '.server-log' }] }, attributes: { actions: [{ actionTypeId }, { actionTypeId: '.server-log' }] },
} as SavedObjectUnsanitizedDoc<RawAlert>; } as SavedObjectUnsanitizedDoc<RawRule>;
expect(isAnyActionSupportIncidents(doc)).toBe(true); expect(isAnyActionSupportIncidents(doc)).toBe(true);
} }
); );
@ -520,7 +520,7 @@ describe('successful migrations', () => {
test('isAnyActionSupportIncidents should return false when there is no connector that supports incidents', () => { test('isAnyActionSupportIncidents should return false when there is no connector that supports incidents', () => {
const doc = { const doc = {
attributes: { actions: [{ actionTypeId: '.server-log' }] }, attributes: { actions: [{ actionTypeId: '.server-log' }] },
} as SavedObjectUnsanitizedDoc<RawAlert>; } as SavedObjectUnsanitizedDoc<RawRule>;
expect(isAnyActionSupportIncidents(doc)).toBe(false); expect(isAnyActionSupportIncidents(doc)).toBe(false);
}); });
@ -2254,7 +2254,7 @@ function getUpdatedAt(): string {
function getMockData( function getMockData(
overwrites: Record<string, unknown> = {}, overwrites: Record<string, unknown> = {},
withSavedObjectUpdatedAt: boolean = false withSavedObjectUpdatedAt: boolean = false
): SavedObjectUnsanitizedDoc<Partial<RawAlert>> { ): SavedObjectUnsanitizedDoc<Partial<RawRule>> {
return { return {
attributes: { attributes: {
enabled: true, enabled: true,

View file

@ -17,7 +17,7 @@ import {
SavedObjectAttribute, SavedObjectAttribute,
SavedObjectReference, SavedObjectReference,
} from '../../../../../src/core/server'; } from '../../../../../src/core/server';
import { RawAlert, RawAlertAction } from '../types'; import { RawRule, RawAlertAction } from '../types';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server'; import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
import type { IsMigrationNeededPredicate } from '../../../encrypted_saved_objects/server'; import type { IsMigrationNeededPredicate } from '../../../encrypted_saved_objects/server';
import { extractRefsFromGeoContainmentAlert } from './geo_containment/migrations'; import { extractRefsFromGeoContainmentAlert } from './geo_containment/migrations';
@ -28,19 +28,19 @@ export const LEGACY_LAST_MODIFIED_VERSION = 'pre-7.10.0';
export const FILEBEAT_7X_INDICATOR_PATH = 'threatintel.indicator'; export const FILEBEAT_7X_INDICATOR_PATH = 'threatintel.indicator';
interface AlertLogMeta extends LogMeta { interface AlertLogMeta extends LogMeta {
migrations: { alertDocument: SavedObjectUnsanitizedDoc<RawAlert> }; migrations: { alertDocument: SavedObjectUnsanitizedDoc<RawRule> };
} }
type AlertMigration = ( type AlertMigration = (
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
) => SavedObjectUnsanitizedDoc<RawAlert>; ) => SavedObjectUnsanitizedDoc<RawRule>;
function createEsoMigration( function createEsoMigration(
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, encryptedSavedObjects: EncryptedSavedObjectsPluginSetup,
isMigrationNeededPredicate: IsMigrationNeededPredicate<RawAlert, RawAlert>, isMigrationNeededPredicate: IsMigrationNeededPredicate<RawRule, RawRule>,
migrationFunc: AlertMigration migrationFunc: AlertMigration
) { ) {
return encryptedSavedObjects.createMigration<RawAlert, RawAlert>({ return encryptedSavedObjects.createMigration<RawRule, RawRule>({
isMigrationNeededPredicate, isMigrationNeededPredicate,
migration: migrationFunc, migration: migrationFunc,
shouldMigrateIfDecryptionFails: true, // shouldMigrateIfDecryptionFails flag that applies the migration to undecrypted document if decryption fails shouldMigrateIfDecryptionFails: true, // shouldMigrateIfDecryptionFails flag that applies the migration to undecrypted document if decryption fails
@ -49,13 +49,13 @@ function createEsoMigration(
const SUPPORT_INCIDENTS_ACTION_TYPES = ['.servicenow', '.jira', '.resilient']; const SUPPORT_INCIDENTS_ACTION_TYPES = ['.servicenow', '.jira', '.resilient'];
export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc<RawAlert>): boolean => export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc<RawRule>): boolean =>
doc.attributes.actions.some((action) => doc.attributes.actions.some((action) =>
SUPPORT_INCIDENTS_ACTION_TYPES.includes(action.actionTypeId) SUPPORT_INCIDENTS_ACTION_TYPES.includes(action.actionTypeId)
); );
// Deprecated in 8.0 // Deprecated in 8.0
export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc<RawAlert>): boolean => export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc<RawRule>): boolean =>
doc.attributes.alertTypeId === 'siem.signals'; doc.attributes.alertTypeId === 'siem.signals';
/** /**
@ -66,7 +66,7 @@ export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc<RawAlert>):
* @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function
*/ */
export const isSecuritySolutionLegacyNotification = ( export const isSecuritySolutionLegacyNotification = (
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): boolean => doc.attributes.alertTypeId === 'siem.notifications'; ): boolean => doc.attributes.alertTypeId === 'siem.notifications';
export function getMigrations( export function getMigrations(
@ -76,7 +76,7 @@ export function getMigrations(
const migrationWhenRBACWasIntroduced = createEsoMigration( const migrationWhenRBACWasIntroduced = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
// migrate all documents in 7.10 in order to add the "meta" RBAC field // migrate all documents in 7.10 in order to add the "meta" RBAC field
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => true, (doc): doc is SavedObjectUnsanitizedDoc<RawRule> => true,
pipeMigrations( pipeMigrations(
markAsLegacyAndChangeConsumer, markAsLegacyAndChangeConsumer,
setAlertIdAsDefaultDedupkeyOnPagerDutyActions, setAlertIdAsDefaultDedupkeyOnPagerDutyActions,
@ -87,37 +87,37 @@ export function getMigrations(
const migrationAlertUpdatedAtAndNotifyWhen = createEsoMigration( const migrationAlertUpdatedAtAndNotifyWhen = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
// migrate all documents in 7.11 in order to add the "updatedAt" and "notifyWhen" fields // migrate all documents in 7.11 in order to add the "updatedAt" and "notifyWhen" fields
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => true, (doc): doc is SavedObjectUnsanitizedDoc<RawRule> => true,
pipeMigrations(setAlertUpdatedAtDate, setNotifyWhen) pipeMigrations(setAlertUpdatedAtDate, setNotifyWhen)
); );
const migrationActions7112 = createEsoMigration( const migrationActions7112 = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isAnyActionSupportIncidents(doc), (doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isAnyActionSupportIncidents(doc),
pipeMigrations(restructureConnectorsThatSupportIncident) pipeMigrations(restructureConnectorsThatSupportIncident)
); );
const migrationSecurityRules713 = createEsoMigration( const migrationSecurityRules713 = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isSiemSignalsRuleType(doc), (doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isSiemSignalsRuleType(doc),
pipeMigrations(removeNullsFromSecurityRules) pipeMigrations(removeNullsFromSecurityRules)
); );
const migrationSecurityRules714 = createEsoMigration( const migrationSecurityRules714 = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isSiemSignalsRuleType(doc), (doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isSiemSignalsRuleType(doc),
pipeMigrations(removeNullAuthorFromSecurityRules) pipeMigrations(removeNullAuthorFromSecurityRules)
); );
const migrationSecurityRules715 = createEsoMigration( const migrationSecurityRules715 = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isSiemSignalsRuleType(doc), (doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isSiemSignalsRuleType(doc),
pipeMigrations(addExceptionListsToReferences) pipeMigrations(addExceptionListsToReferences)
); );
const migrateRules716 = createEsoMigration( const migrateRules716 = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => true, (doc): doc is SavedObjectUnsanitizedDoc<RawRule> => true,
pipeMigrations( pipeMigrations(
setLegacyId, setLegacyId,
getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured), getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured),
@ -128,7 +128,7 @@ export function getMigrations(
const migrationRules800 = createEsoMigration( const migrationRules800 = createEsoMigration(
encryptedSavedObjects, encryptedSavedObjects,
(doc: SavedObjectUnsanitizedDoc<RawAlert>): doc is SavedObjectUnsanitizedDoc<RawAlert> => true, (doc: SavedObjectUnsanitizedDoc<RawRule>): doc is SavedObjectUnsanitizedDoc<RawRule> => true,
pipeMigrations( pipeMigrations(
addThreatIndicatorPathToThreatMatchRules, addThreatIndicatorPathToThreatMatchRules,
addRACRuleTypes, addRACRuleTypes,
@ -149,10 +149,10 @@ export function getMigrations(
} }
function executeMigrationWithErrorHandling( function executeMigrationWithErrorHandling(
migrationFunc: SavedObjectMigrationFn<RawAlert, RawAlert>, migrationFunc: SavedObjectMigrationFn<RawRule, RawRule>,
version: string version: string
) { ) {
return (doc: SavedObjectUnsanitizedDoc<RawAlert>, context: SavedObjectMigrationContext) => { return (doc: SavedObjectUnsanitizedDoc<RawRule>, context: SavedObjectMigrationContext) => {
try { try {
return migrationFunc(doc, context); return migrationFunc(doc, context);
} catch (ex) { } catch (ex) {
@ -170,8 +170,8 @@ function executeMigrationWithErrorHandling(
} }
const setAlertUpdatedAtDate = ( const setAlertUpdatedAtDate = (
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> => { ): SavedObjectUnsanitizedDoc<RawRule> => {
const updatedAt = doc.updated_at || doc.attributes.createdAt; const updatedAt = doc.updated_at || doc.attributes.createdAt;
return { return {
...doc, ...doc,
@ -183,8 +183,8 @@ const setAlertUpdatedAtDate = (
}; };
const setNotifyWhen = ( const setNotifyWhen = (
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> => { ): SavedObjectUnsanitizedDoc<RawRule> => {
const notifyWhen = doc.attributes.throttle ? 'onThrottleInterval' : 'onActiveAlert'; const notifyWhen = doc.attributes.throttle ? 'onThrottleInterval' : 'onActiveAlert';
return { return {
...doc, ...doc,
@ -204,8 +204,8 @@ const consumersToChange: Map<string, string> = new Map(
); );
function markAsLegacyAndChangeConsumer( function markAsLegacyAndChangeConsumer(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { const {
attributes: { consumer }, attributes: { consumer },
} = doc; } = doc;
@ -223,8 +223,8 @@ function markAsLegacyAndChangeConsumer(
} }
function setAlertIdAsDefaultDedupkeyOnPagerDutyActions( function setAlertIdAsDefaultDedupkeyOnPagerDutyActions(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { attributes } = doc; const { attributes } = doc;
return { return {
...doc, ...doc,
@ -251,8 +251,8 @@ function setAlertIdAsDefaultDedupkeyOnPagerDutyActions(
} }
function initializeExecutionStatus( function initializeExecutionStatus(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { attributes } = doc; const { attributes } = doc;
return { return {
...doc, ...doc,
@ -277,8 +277,8 @@ function isEmptyObject(obj: {}) {
} }
function restructureConnectorsThatSupportIncident( function restructureConnectorsThatSupportIncident(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { actions } = doc.attributes; const { actions } = doc.attributes;
const newActions = actions.reduce((acc, action) => { const newActions = actions.reduce((acc, action) => {
if ( if (
@ -416,8 +416,8 @@ function convertNullToUndefined(attribute: SavedObjectAttribute) {
} }
function removeNullsFromSecurityRules( function removeNullsFromSecurityRules(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { const {
attributes: { params }, attributes: { params },
} = doc; } = doc;
@ -490,8 +490,8 @@ function removeNullsFromSecurityRules(
* @returns The document with the author field fleshed in. * @returns The document with the author field fleshed in.
*/ */
function removeNullAuthorFromSecurityRules( function removeNullAuthorFromSecurityRules(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { const {
attributes: { params }, attributes: { params },
} = doc; } = doc;
@ -519,8 +519,8 @@ function removeNullAuthorFromSecurityRules(
* @returns The document migrated with saved object references * @returns The document migrated with saved object references
*/ */
function addExceptionListsToReferences( function addExceptionListsToReferences(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { const {
attributes: { attributes: {
params: { exceptionsList }, params: { exceptionsList },
@ -610,8 +610,8 @@ function removeMalformedExceptionsList(
* @returns The document migrated with saved object references * @returns The document migrated with saved object references
*/ */
function addRuleIdsToLegacyNotificationReferences( function addRuleIdsToLegacyNotificationReferences(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { const {
attributes: { attributes: {
params: { ruleAlertId }, params: { ruleAlertId },
@ -641,9 +641,7 @@ function addRuleIdsToLegacyNotificationReferences(
} }
} }
function setLegacyId( function setLegacyId(doc: SavedObjectUnsanitizedDoc<RawRule>): SavedObjectUnsanitizedDoc<RawRule> {
doc: SavedObjectUnsanitizedDoc<RawAlert>
): SavedObjectUnsanitizedDoc<RawAlert> {
const { id } = doc; const { id } = doc;
return { return {
...doc, ...doc,
@ -655,8 +653,8 @@ function setLegacyId(
} }
function addRACRuleTypes( function addRACRuleTypes(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const ruleType = doc.attributes.params.type; const ruleType = doc.attributes.params.type;
return isSiemSignalsRuleType(doc) && isRuleType(ruleType) return isSiemSignalsRuleType(doc) && isRuleType(ruleType)
? { ? {
@ -674,8 +672,8 @@ function addRACRuleTypes(
} }
function addThreatIndicatorPathToThreatMatchRules( function addThreatIndicatorPathToThreatMatchRules(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
return isSiemSignalsRuleType(doc) && return isSiemSignalsRuleType(doc) &&
doc.attributes.params?.type === 'threat_match' && doc.attributes.params?.type === 'threat_match' &&
!doc.attributes.params.threatIndicatorPath !doc.attributes.params.threatIndicatorPath
@ -695,15 +693,15 @@ function addThreatIndicatorPathToThreatMatchRules(
function getRemovePreconfiguredConnectorsFromReferencesFn( function getRemovePreconfiguredConnectorsFromReferencesFn(
isPreconfigured: (connectorId: string) => boolean isPreconfigured: (connectorId: string) => boolean
) { ) {
return (doc: SavedObjectUnsanitizedDoc<RawAlert>) => { return (doc: SavedObjectUnsanitizedDoc<RawRule>) => {
return removePreconfiguredConnectorsFromReferences(doc, isPreconfigured); return removePreconfiguredConnectorsFromReferences(doc, isPreconfigured);
}; };
} }
function removePreconfiguredConnectorsFromReferences( function removePreconfiguredConnectorsFromReferences(
doc: SavedObjectUnsanitizedDoc<RawAlert>, doc: SavedObjectUnsanitizedDoc<RawRule>,
isPreconfigured: (connectorId: string) => boolean isPreconfigured: (connectorId: string) => boolean
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
const { const {
attributes: { actions }, attributes: { actions },
references, references,
@ -719,7 +717,7 @@ function removePreconfiguredConnectorsFromReferences(
); );
const updatedConnectorReferences: SavedObjectReference[] = []; const updatedConnectorReferences: SavedObjectReference[] = [];
const updatedActions: RawAlert['actions'] = []; const updatedActions: RawRule['actions'] = [];
// For each connector reference, check if connector is preconfigured // For each connector reference, check if connector is preconfigured
// If yes, we need to remove from the references array and update // If yes, we need to remove from the references array and update
@ -758,8 +756,8 @@ function removePreconfiguredConnectorsFromReferences(
// This fixes an issue whereby metrics.alert.inventory.threshold rules had the // This fixes an issue whereby metrics.alert.inventory.threshold rules had the
// group for actions incorrectly spelt as metrics.invenotry_threshold.fired vs metrics.inventory_threshold.fired // group for actions incorrectly spelt as metrics.invenotry_threshold.fired vs metrics.inventory_threshold.fired
function fixInventoryThresholdGroupId( function fixInventoryThresholdGroupId(
doc: SavedObjectUnsanitizedDoc<RawAlert> doc: SavedObjectUnsanitizedDoc<RawRule>
): SavedObjectUnsanitizedDoc<RawAlert> { ): SavedObjectUnsanitizedDoc<RawRule> {
if (doc.attributes.alertTypeId === 'metrics.alert.inventory.threshold') { if (doc.attributes.alertTypeId === 'metrics.alert.inventory.threshold') {
const { const {
attributes: { actions }, attributes: { actions },
@ -805,6 +803,6 @@ function getCorrespondingAction(
} }
function pipeMigrations(...migrations: AlertMigration[]): AlertMigration { function pipeMigrations(...migrations: AlertMigration[]): AlertMigration {
return (doc: SavedObjectUnsanitizedDoc<RawAlert>) => return (doc: SavedObjectUnsanitizedDoc<RawRule>) =>
migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc); migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc);
} }

View file

@ -6,7 +6,7 @@
*/ */
import { pick } from 'lodash'; import { pick } from 'lodash';
import { RawAlert } from '../types'; import { RawRule } from '../types';
import { import {
SavedObjectsClient, SavedObjectsClient,
@ -17,7 +17,7 @@ import {
import { AlertAttributesExcludedFromAAD, AlertAttributesExcludedFromAADType } from './index'; import { AlertAttributesExcludedFromAAD, AlertAttributesExcludedFromAADType } from './index';
export type PartiallyUpdateableAlertAttributes = Partial< export type PartiallyUpdateableAlertAttributes = Partial<
Pick<RawAlert, AlertAttributesExcludedFromAADType> Pick<RawRule, AlertAttributesExcludedFromAADType>
>; >;
export interface PartiallyUpdateAlertSavedObjectOptions { export interface PartiallyUpdateAlertSavedObjectOptions {
@ -40,7 +40,7 @@ export async function partiallyUpdateAlert(
): Promise<void> { ): Promise<void> {
// ensure we only have the valid attributes excluded from AAD // ensure we only have the valid attributes excluded from AAD
const attributeUpdates = pick(attributes, AlertAttributesExcludedFromAAD); const attributeUpdates = pick(attributes, AlertAttributesExcludedFromAAD);
const updateOptions: SavedObjectsUpdateOptions<RawAlert> = pick( const updateOptions: SavedObjectsUpdateOptions<RawRule> = pick(
options, options,
'namespace', 'namespace',
'version', 'version',
@ -48,7 +48,7 @@ export async function partiallyUpdateAlert(
); );
try { try {
await savedObjectsClient.update<RawAlert>('alert', id, attributeUpdates, updateOptions); await savedObjectsClient.update<RawRule>('alert', id, attributeUpdates, updateOptions);
} catch (err) { } catch (err) {
if (options?.ignore404 && SavedObjectsErrorHelpers.isNotFoundError(err)) { if (options?.ignore404 && SavedObjectsErrorHelpers.isNotFoundError(err)) {
return; return;

View file

@ -6,8 +6,8 @@
*/ */
import { transformRulesForExport } from './transform_rule_for_export'; import { transformRulesForExport } from './transform_rule_for_export';
jest.mock('../lib/alert_execution_status', () => ({ jest.mock('../lib/rule_execution_status', () => ({
getAlertExecutionStatusPending: () => ({ getRuleExecutionStatusPending: () => ({
status: 'pending', status: 'pending',
lastExecutionDate: '2020-08-20T19:23:38Z', lastExecutionDate: '2020-08-20T19:23:38Z',
error: null, error: null,

View file

@ -6,18 +6,18 @@
*/ */
import { SavedObject } from 'kibana/server'; import { SavedObject } from 'kibana/server';
import { getAlertExecutionStatusPending } from '../lib/alert_execution_status'; import { getRuleExecutionStatusPending } from '../lib/rule_execution_status';
import { RawAlert } from '../types'; import { RawRule } from '../types';
export function transformRulesForExport(rules: SavedObject[]): Array<SavedObject<RawAlert>> { export function transformRulesForExport(rules: SavedObject[]): Array<SavedObject<RawRule>> {
const exportDate = new Date().toISOString(); const exportDate = new Date().toISOString();
return rules.map((rule) => transformRuleForExport(rule as SavedObject<RawAlert>, exportDate)); return rules.map((rule) => transformRuleForExport(rule as SavedObject<RawRule>, exportDate));
} }
function transformRuleForExport( function transformRuleForExport(
rule: SavedObject<RawAlert>, rule: SavedObject<RawRule>,
exportDate: string exportDate: string
): SavedObject<RawAlert> { ): SavedObject<RawRule> {
return { return {
...rule, ...rule,
attributes: { attributes: {
@ -27,7 +27,7 @@ function transformRuleForExport(
apiKey: null, apiKey: null,
apiKeyOwner: null, apiKeyOwner: null,
scheduledTaskId: null, scheduledTaskId: null,
executionStatus: getAlertExecutionStatusPending(exportDate), executionStatus: getRuleExecutionStatusPending(exportDate),
}, },
}; };
} }

View file

@ -11,16 +11,16 @@ import { fold } from 'fp-ts/lib/Either';
import { ConcreteTaskInstance } from '../../../task_manager/server'; import { ConcreteTaskInstance } from '../../../task_manager/server';
import { import {
SanitizedAlert, SanitizedAlert,
AlertTaskState, RuleTaskState,
alertParamsSchema, ruleParamsSchema,
alertStateSchema, ruleStateSchema,
AlertTaskParams, RuleTaskParams,
AlertTypeParams, AlertTypeParams,
} from '../../common'; } from '../../common';
export interface AlertTaskInstance extends ConcreteTaskInstance { export interface AlertTaskInstance extends ConcreteTaskInstance {
state: AlertTaskState; state: RuleTaskState;
params: AlertTaskParams; params: RuleTaskParams;
} }
const enumerateErrorFields = (e: t.Errors) => const enumerateErrorFields = (e: t.Errors) =>
@ -33,7 +33,7 @@ export function taskInstanceToAlertTaskInstance<Params extends AlertTypeParams>(
return { return {
...taskInstance, ...taskInstance,
params: pipe( params: pipe(
alertParamsSchema.decode(taskInstance.params), ruleParamsSchema.decode(taskInstance.params),
fold((e: t.Errors) => { fold((e: t.Errors) => {
throw new Error( throw new Error(
`Task "${taskInstance.id}" ${ `Task "${taskInstance.id}" ${
@ -43,7 +43,7 @@ export function taskInstanceToAlertTaskInstance<Params extends AlertTypeParams>(
}, t.identity) }, t.identity)
), ),
state: pipe( state: pipe(
alertStateSchema.decode(taskInstance.state), ruleStateSchema.decode(taskInstance.state),
fold((e: t.Errors) => { fold((e: t.Errors) => {
throw new Error( throw new Error(
`Task "${taskInstance.id}" ${ `Task "${taskInstance.id}" ${

View file

@ -16,7 +16,7 @@ import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';
import { KibanaRequest } from 'kibana/server'; import { KibanaRequest } from 'kibana/server';
import { asSavedObjectExecutionSource } from '../../../actions/server'; import { asSavedObjectExecutionSource } from '../../../actions/server';
import { InjectActionParamsOpts } from './inject_action_params'; import { InjectActionParamsOpts } from './inject_action_params';
import { NormalizedAlertType } from '../rule_type_registry'; import { NormalizedRuleType } from '../rule_type_registry';
import { import {
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
@ -28,7 +28,7 @@ jest.mock('./inject_action_params', () => ({
injectActionParams: jest.fn(), injectActionParams: jest.fn(),
})); }));
const alertType: NormalizedAlertType< const ruleType: NormalizedRuleType<
AlertTypeParams, AlertTypeParams,
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
@ -71,12 +71,12 @@ const createExecutionHandlerParams: jest.Mocked<
> = { > = {
actionsPlugin: mockActionsPlugin, actionsPlugin: mockActionsPlugin,
spaceId: 'test1', spaceId: 'test1',
alertId: '1', ruleId: '1',
alertName: 'name-of-alert', ruleName: 'name-of-alert',
tags: ['tag-A', 'tag-B'], tags: ['tag-A', 'tag-B'],
apiKey: 'MTIzOmFiYw==', apiKey: 'MTIzOmFiYw==',
kibanaBaseUrl: 'http://localhost:5601', kibanaBaseUrl: 'http://localhost:5601',
alertType, ruleType,
logger: loggingSystemMock.create().get(), logger: loggingSystemMock.create().get(),
eventLogger: mockEventLogger, eventLogger: mockEventLogger,
actions: [ actions: [
@ -93,13 +93,13 @@ const createExecutionHandlerParams: jest.Mocked<
}, },
], ],
request: {} as KibanaRequest, request: {} as KibanaRequest,
alertParams: { ruleParams: {
foo: true, foo: true,
contextVal: 'My other {{context.value}} goes here', contextVal: 'My other {{context.value}} goes here',
stateVal: 'My other {{state.value}} goes here', stateVal: 'My other {{state.value}} goes here',
}, },
supportsEphemeralTasks: false, supportsEphemeralTasks: false,
maxEphemeralActionsPerAlert: 10, maxEphemeralActionsPerRule: 10,
}; };
beforeEach(() => { beforeEach(() => {
@ -123,7 +123,7 @@ test('enqueues execution per selected action', async () => {
actionGroup: 'default', actionGroup: 'default',
state: {}, state: {},
context: {}, context: {},
alertInstanceId: '2', alertId: '2',
}); });
expect(mockActionsPlugin.getActionsClientWithRequest).toHaveBeenCalledWith( expect(mockActionsPlugin.getActionsClientWithRequest).toHaveBeenCalledWith(
createExecutionHandlerParams.request createExecutionHandlerParams.request
@ -244,7 +244,7 @@ test(`doesn't call actionsPlugin.execute for disabled actionTypes`, async () =>
actionGroup: 'default', actionGroup: 'default',
state: {}, state: {},
context: {}, context: {},
alertInstanceId: '2', alertId: '2',
}); });
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
expect(actionsClient.enqueueExecution).toHaveBeenCalledWith({ expect(actionsClient.enqueueExecution).toHaveBeenCalledWith({
@ -296,7 +296,7 @@ test('trow error error message when action type is disabled', async () => {
actionGroup: 'default', actionGroup: 'default',
state: {}, state: {},
context: {}, context: {},
alertInstanceId: '2', alertId: '2',
}); });
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(0); expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(0);
@ -310,7 +310,7 @@ test('trow error error message when action type is disabled', async () => {
actionGroup: 'default', actionGroup: 'default',
state: {}, state: {},
context: {}, context: {},
alertInstanceId: '2', alertId: '2',
}); });
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
}); });
@ -321,7 +321,7 @@ test('limits actionsPlugin.execute per action group', async () => {
actionGroup: 'other-group', actionGroup: 'other-group',
state: {}, state: {},
context: {}, context: {},
alertInstanceId: '2', alertId: '2',
}); });
expect(actionsClient.enqueueExecution).not.toHaveBeenCalled(); expect(actionsClient.enqueueExecution).not.toHaveBeenCalled();
}); });
@ -332,7 +332,7 @@ test('context attribute gets parameterized', async () => {
actionGroup: 'default', actionGroup: 'default',
context: { value: 'context-val' }, context: { value: 'context-val' },
state: {}, state: {},
alertInstanceId: '2', alertId: '2',
}); });
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(`
@ -373,7 +373,7 @@ test('state attribute gets parameterized', async () => {
actionGroup: 'default', actionGroup: 'default',
context: {}, context: {},
state: { value: 'state-val' }, state: { value: 'state-val' },
alertInstanceId: '2', alertId: '2',
}); });
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(`
@ -408,7 +408,7 @@ test('state attribute gets parameterized', async () => {
`); `);
}); });
test(`logs an error when action group isn't part of actionGroups available for the alertType`, async () => { test(`logs an error when action group isn't part of actionGroups available for the ruleType`, async () => {
const executionHandler = createExecutionHandler(createExecutionHandlerParams); const executionHandler = createExecutionHandler(createExecutionHandlerParams);
const result = await executionHandler({ const result = await executionHandler({
// we have to trick the compiler as this is an invalid type and this test checks whether we // we have to trick the compiler as this is an invalid type and this test checks whether we
@ -416,10 +416,10 @@ test(`logs an error when action group isn't part of actionGroups available for t
actionGroup: 'invalid-group' as 'default' | 'other-group', actionGroup: 'invalid-group' as 'default' | 'other-group',
context: {}, context: {},
state: {}, state: {},
alertInstanceId: '2', alertId: '2',
}); });
expect(result).toBeUndefined(); expect(result).toBeUndefined();
expect(createExecutionHandlerParams.logger.error).toHaveBeenCalledWith( expect(createExecutionHandlerParams.logger.error).toHaveBeenCalledWith(
'Invalid action group "invalid-group" for alert "test".' 'Invalid action group "invalid-group" for rule "test".'
); );
}); });

View file

@ -19,9 +19,9 @@ import {
AlertTypeState, AlertTypeState,
AlertInstanceState, AlertInstanceState,
AlertInstanceContext, AlertInstanceContext,
RawAlert, RawRule,
} from '../types'; } from '../types';
import { NormalizedAlertType, UntypedNormalizedAlertType } from '../rule_type_registry'; import { NormalizedRuleType, UntypedNormalizedRuleType } from '../rule_type_registry';
import { isEphemeralTaskRejectedDueToCapacityError } from '../../../task_manager/server'; import { isEphemeralTaskRejectedDueToCapacityError } from '../../../task_manager/server';
import { createAlertEventLogRecordObject } from '../lib/create_alert_event_log_record_object'; import { createAlertEventLogRecordObject } from '../lib/create_alert_event_log_record_object';
@ -34,15 +34,15 @@ export interface CreateExecutionHandlerOptions<
ActionGroupIds extends string, ActionGroupIds extends string,
RecoveryActionGroupId extends string RecoveryActionGroupId extends string
> { > {
alertId: string; ruleId: string;
alertName: string; ruleName: string;
tags?: string[]; tags?: string[];
actionsPlugin: ActionsPluginStartContract; actionsPlugin: ActionsPluginStartContract;
actions: AlertAction[]; actions: AlertAction[];
spaceId: string; spaceId: string;
apiKey: RawAlert['apiKey']; apiKey: RawRule['apiKey'];
kibanaBaseUrl: string | undefined; kibanaBaseUrl: string | undefined;
alertType: NormalizedAlertType< ruleType: NormalizedRuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -54,15 +54,15 @@ export interface CreateExecutionHandlerOptions<
logger: Logger; logger: Logger;
eventLogger: IEventLogger; eventLogger: IEventLogger;
request: KibanaRequest; request: KibanaRequest;
alertParams: AlertTypeParams; ruleParams: AlertTypeParams;
supportsEphemeralTasks: boolean; supportsEphemeralTasks: boolean;
maxEphemeralActionsPerAlert: number; maxEphemeralActionsPerRule: number;
} }
interface ExecutionHandlerOptions<ActionGroupIds extends string> { interface ExecutionHandlerOptions<ActionGroupIds extends string> {
actionGroup: ActionGroupIds; actionGroup: ActionGroupIds;
actionSubgroup?: string; actionSubgroup?: string;
alertInstanceId: string; alertId: string;
context: AlertInstanceContext; context: AlertInstanceContext;
state: AlertInstanceState; state: AlertInstanceState;
} }
@ -81,20 +81,20 @@ export function createExecutionHandler<
RecoveryActionGroupId extends string RecoveryActionGroupId extends string
>({ >({
logger, logger,
alertId, ruleId,
alertName, ruleName,
tags, tags,
actionsPlugin, actionsPlugin,
actions: alertActions, actions: ruleActions,
spaceId, spaceId,
apiKey, apiKey,
alertType, ruleType,
kibanaBaseUrl, kibanaBaseUrl,
eventLogger, eventLogger,
request, request,
alertParams, ruleParams,
supportsEphemeralTasks, supportsEphemeralTasks,
maxEphemeralActionsPerAlert, maxEphemeralActionsPerRule,
}: CreateExecutionHandlerOptions< }: CreateExecutionHandlerOptions<
Params, Params,
ExtractedParams, ExtractedParams,
@ -104,66 +104,66 @@ export function createExecutionHandler<
ActionGroupIds, ActionGroupIds,
RecoveryActionGroupId RecoveryActionGroupId
>): ExecutionHandler<ActionGroupIds | RecoveryActionGroupId> { >): ExecutionHandler<ActionGroupIds | RecoveryActionGroupId> {
const alertTypeActionGroups = new Map( const ruleTypeActionGroups = new Map(
alertType.actionGroups.map((actionGroup) => [actionGroup.id, actionGroup.name]) ruleType.actionGroups.map((actionGroup) => [actionGroup.id, actionGroup.name])
); );
return async ({ return async ({
actionGroup, actionGroup,
actionSubgroup, actionSubgroup,
context, context,
state, state,
alertInstanceId, alertId,
}: ExecutionHandlerOptions<ActionGroupIds | RecoveryActionGroupId>) => { }: ExecutionHandlerOptions<ActionGroupIds | RecoveryActionGroupId>) => {
if (!alertTypeActionGroups.has(actionGroup)) { if (!ruleTypeActionGroups.has(actionGroup)) {
logger.error(`Invalid action group "${actionGroup}" for alert "${alertType.id}".`); logger.error(`Invalid action group "${actionGroup}" for rule "${ruleType.id}".`);
return; return;
} }
const actions = alertActions const actions = ruleActions
.filter(({ group }) => group === actionGroup) .filter(({ group }) => group === actionGroup)
.map((action) => { .map((action) => {
return { return {
...action, ...action,
params: transformActionParams({ params: transformActionParams({
actionsPlugin, actionsPlugin,
alertId, alertId: ruleId,
alertType: alertType.id, alertType: ruleType.id,
actionTypeId: action.actionTypeId, actionTypeId: action.actionTypeId,
alertName, alertName: ruleName,
spaceId, spaceId,
tags, tags,
alertInstanceId, alertInstanceId: alertId,
alertActionGroup: actionGroup, alertActionGroup: actionGroup,
alertActionGroupName: alertTypeActionGroups.get(actionGroup)!, alertActionGroupName: ruleTypeActionGroups.get(actionGroup)!,
alertActionSubgroup: actionSubgroup, alertActionSubgroup: actionSubgroup,
context, context,
actionParams: action.params, actionParams: action.params,
actionId: action.id, actionId: action.id,
state, state,
kibanaBaseUrl, kibanaBaseUrl,
alertParams, alertParams: ruleParams,
}), }),
}; };
}) })
.map((action) => ({ .map((action) => ({
...action, ...action,
params: injectActionParams({ params: injectActionParams({
ruleId: alertId, ruleId,
spaceId, spaceId,
actionParams: action.params, actionParams: action.params,
actionTypeId: action.actionTypeId, actionTypeId: action.actionTypeId,
}), }),
})); }));
const alertLabel = `${alertType.id}:${alertId}: '${alertName}'`; const ruleLabel = `${ruleType.id}:${ruleId}: '${ruleName}'`;
const actionsClient = await actionsPlugin.getActionsClientWithRequest(request); const actionsClient = await actionsPlugin.getActionsClientWithRequest(request);
let ephemeralActionsToSchedule = maxEphemeralActionsPerAlert; let ephemeralActionsToSchedule = maxEphemeralActionsPerRule;
for (const action of actions) { for (const action of actions) {
if ( if (
!actionsPlugin.isActionExecutable(action.id, action.actionTypeId, { notifyUsage: true }) !actionsPlugin.isActionExecutable(action.id, action.actionTypeId, { notifyUsage: true })
) { ) {
logger.warn( logger.warn(
`Alert "${alertId}" skipped scheduling action "${action.id}" because it is disabled` `Rule "${ruleId}" skipped scheduling action "${action.id}" because it is disabled`
); );
continue; continue;
} }
@ -176,15 +176,15 @@ export function createExecutionHandler<
spaceId, spaceId,
apiKey: apiKey ?? null, apiKey: apiKey ?? null,
source: asSavedObjectExecutionSource({ source: asSavedObjectExecutionSource({
id: alertId, id: ruleId,
type: 'alert', type: 'alert',
}), }),
relatedSavedObjects: [ relatedSavedObjects: [
{ {
id: alertId, id: ruleId,
type: 'alert', type: 'alert',
namespace: namespace.namespace, namespace: namespace.namespace,
typeId: alertType.id, typeId: ruleType.id,
}, },
], ],
}; };
@ -203,18 +203,18 @@ export function createExecutionHandler<
} }
const event = createAlertEventLogRecordObject({ const event = createAlertEventLogRecordObject({
ruleId: alertId, ruleId,
ruleType: alertType as UntypedNormalizedAlertType, ruleType: ruleType as UntypedNormalizedRuleType,
action: EVENT_LOG_ACTIONS.executeAction, action: EVENT_LOG_ACTIONS.executeAction,
instanceId: alertInstanceId, instanceId: alertId,
group: actionGroup, group: actionGroup,
subgroup: actionSubgroup, subgroup: actionSubgroup,
ruleName: alertName, ruleName,
savedObjects: [ savedObjects: [
{ {
type: 'alert', type: 'alert',
id: alertId, id: ruleId,
typeId: alertType.id, typeId: ruleType.id,
relation: SAVED_OBJECT_REL_PRIMARY, relation: SAVED_OBJECT_REL_PRIMARY,
}, },
{ {
@ -224,7 +224,7 @@ export function createExecutionHandler<
}, },
], ],
...namespace, ...namespace,
message: `alert: ${alertLabel} instanceId: '${alertInstanceId}' scheduled ${ message: `alert: ${ruleLabel} instanceId: '${alertId}' scheduled ${
actionSubgroup actionSubgroup
? `actionGroup(subgroup): '${actionGroup}(${actionSubgroup})'` ? `actionGroup(subgroup): '${actionGroup}(${actionSubgroup})'`
: `actionGroup: '${actionGroup}'` : `actionGroup: '${actionGroup}'`

File diff suppressed because it is too large Load diff

View file

@ -29,10 +29,10 @@ import { alertsMock, rulesClientMock } from '../mocks';
import { eventLoggerMock } from '../../../event_log/server/event_logger.mock'; import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';
import { IEventLogger } from '../../../event_log/server'; import { IEventLogger } from '../../../event_log/server';
import { Alert, RecoveredActionGroup } from '../../common'; import { Alert, RecoveredActionGroup } from '../../common';
import { UntypedNormalizedAlertType } from '../rule_type_registry'; import { UntypedNormalizedRuleType } from '../rule_type_registry';
import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock';
const ruleType: jest.Mocked<UntypedNormalizedAlertType> = { const ruleType: jest.Mocked<UntypedNormalizedRuleType> = {
id: 'test', id: 'test',
name: 'My test rule', name: 'My test rule',
actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup], actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup],
@ -100,7 +100,7 @@ describe('Task Runner Cancel', () => {
ruleTypeRegistry, ruleTypeRegistry,
kibanaBaseUrl: 'https://localhost:5601', kibanaBaseUrl: 'https://localhost:5601',
supportsEphemeralTasks: false, supportsEphemeralTasks: false,
maxEphemeralActionsPerAlert: 10, maxEphemeralActionsPerRule: 10,
cancelAlertsOnRuleTimeout: true, cancelAlertsOnRuleTimeout: true,
}; };
@ -215,7 +215,7 @@ describe('Task Runner Cancel', () => {
scheduled: '1970-01-01T00:00:00.000Z', scheduled: '1970-01-01T00:00:00.000Z',
}, },
}, },
message: 'alert execution start: "1"', message: 'rule execution start: "1"',
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',
@ -271,7 +271,7 @@ describe('Task Runner Cancel', () => {
scheduled: '1970-01-01T00:00:00.000Z', scheduled: '1970-01-01T00:00:00.000Z',
}, },
}, },
message: `alert executed: test:1: 'rule-name'`, message: `rule executed: test:1: 'rule-name'`,
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',
@ -395,7 +395,7 @@ describe('Task Runner Cancel', () => {
const logger = taskRunnerFactoryInitializerParams.logger; const logger = taskRunnerFactoryInitializerParams.logger;
expect(logger.debug).toHaveBeenCalledTimes(6); expect(logger.debug).toHaveBeenCalledTimes(6);
expect(logger.debug).nthCalledWith(1, 'executing alert test:1 at 1970-01-01T00:00:00.000Z'); expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z');
expect(logger.debug).nthCalledWith( expect(logger.debug).nthCalledWith(
2, 2,
`Cancelling rule type test with id 1 - execution exceeded rule type timeout of 5m` `Cancelling rule type test with id 1 - execution exceeded rule type timeout of 5m`
@ -406,15 +406,15 @@ describe('Task Runner Cancel', () => {
); );
expect(logger.debug).nthCalledWith( expect(logger.debug).nthCalledWith(
4, 4,
`alert test:1: 'rule-name' has 1 active alert instances: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` `rule test:1: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]`
); );
expect(logger.debug).nthCalledWith( expect(logger.debug).nthCalledWith(
5, 5,
`no scheduling of actions for alert test:1: 'rule-name': alert execution has been cancelled.` `no scheduling of actions for rule test:1: 'rule-name': rule execution has been cancelled.`
); );
expect(logger.debug).nthCalledWith( expect(logger.debug).nthCalledWith(
6, 6,
'alertExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}'
); );
const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; const eventLogger = taskRunnerFactoryInitializerParams.eventLogger;
@ -440,7 +440,7 @@ describe('Task Runner Cancel', () => {
}, },
], ],
}, },
message: `alert execution start: \"1\"`, message: `rule execution start: \"1\"`,
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',
@ -498,7 +498,7 @@ describe('Task Runner Cancel', () => {
}, },
], ],
}, },
message: "alert executed: test:1: 'rule-name'", message: "rule executed: test:1: 'rule-name'",
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',
@ -512,7 +512,7 @@ describe('Task Runner Cancel', () => {
function testActionsExecute() { function testActionsExecute() {
const logger = taskRunnerFactoryInitializerParams.logger; const logger = taskRunnerFactoryInitializerParams.logger;
expect(logger.debug).toHaveBeenCalledTimes(5); expect(logger.debug).toHaveBeenCalledTimes(5);
expect(logger.debug).nthCalledWith(1, 'executing alert test:1 at 1970-01-01T00:00:00.000Z'); expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z');
expect(logger.debug).nthCalledWith( expect(logger.debug).nthCalledWith(
2, 2,
`Cancelling rule type test with id 1 - execution exceeded rule type timeout of 5m` `Cancelling rule type test with id 1 - execution exceeded rule type timeout of 5m`
@ -523,11 +523,11 @@ describe('Task Runner Cancel', () => {
); );
expect(logger.debug).nthCalledWith( expect(logger.debug).nthCalledWith(
4, 4,
`alert test:1: 'rule-name' has 1 active alert instances: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` `rule test:1: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]`
); );
expect(logger.debug).nthCalledWith( expect(logger.debug).nthCalledWith(
5, 5,
'alertExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}'
); );
const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; const eventLogger = taskRunnerFactoryInitializerParams.eventLogger;
@ -553,7 +553,7 @@ describe('Task Runner Cancel', () => {
}, },
], ],
}, },
message: `alert execution start: "1"`, message: `rule execution start: "1"`,
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',
@ -609,7 +609,7 @@ describe('Task Runner Cancel', () => {
}, },
], ],
}, },
message: "test:1: 'rule-name' created new instance: '1'", message: "test:1: 'rule-name' created new alert: '1'",
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',
@ -636,7 +636,7 @@ describe('Task Runner Cancel', () => {
{ id: '1', namespace: undefined, rel: 'primary', type: 'alert', type_id: 'test' }, { id: '1', namespace: undefined, rel: 'primary', type: 'alert', type_id: 'test' },
], ],
}, },
message: "test:1: 'rule-name' active instance: '1' in actionGroup: 'default'", message: "test:1: 'rule-name' active alert: '1' in actionGroup: 'default'",
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',
@ -700,7 +700,7 @@ describe('Task Runner Cancel', () => {
}, },
], ],
}, },
message: "alert executed: test:1: 'rule-name'", message: "rule executed: test:1: 'rule-name'",
rule: { rule: {
category: 'test', category: 'test',
id: '1', id: '1',

View file

@ -17,13 +17,13 @@ import {
import { actionsMock } from '../../../actions/server/mocks'; import { actionsMock } from '../../../actions/server/mocks';
import { alertsMock, rulesClientMock } from '../mocks'; import { alertsMock, rulesClientMock } from '../mocks';
import { eventLoggerMock } from '../../../event_log/server/event_logger.mock'; import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';
import { UntypedNormalizedAlertType } from '../rule_type_registry'; import { UntypedNormalizedRuleType } from '../rule_type_registry';
import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock';
import { executionContextServiceMock } from '../../../../../src/core/server/mocks'; import { executionContextServiceMock } from '../../../../../src/core/server/mocks';
const executionContext = executionContextServiceMock.createSetupContract(); const executionContext = executionContextServiceMock.createSetupContract();
const alertType: UntypedNormalizedAlertType = { const ruleType: UntypedNormalizedRuleType = {
id: 'test', id: 'test',
name: 'My test alert', name: 'My test alert',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -83,7 +83,7 @@ describe('Task Runner Factory', () => {
ruleTypeRegistry: ruleTypeRegistryMock.create(), ruleTypeRegistry: ruleTypeRegistryMock.create(),
kibanaBaseUrl: 'https://localhost:5601', kibanaBaseUrl: 'https://localhost:5601',
supportsEphemeralTasks: true, supportsEphemeralTasks: true,
maxEphemeralActionsPerAlert: 10, maxEphemeralActionsPerRule: 10,
cancelAlertsOnRuleTimeout: true, cancelAlertsOnRuleTimeout: true,
executionContext, executionContext,
}; };
@ -96,7 +96,7 @@ describe('Task Runner Factory', () => {
test(`throws an error if factory isn't initialized`, () => { test(`throws an error if factory isn't initialized`, () => {
const factory = new TaskRunnerFactory(); const factory = new TaskRunnerFactory();
expect(() => expect(() =>
factory.create(alertType, { taskInstance: mockedTaskInstance }) factory.create(ruleType, { taskInstance: mockedTaskInstance })
).toThrowErrorMatchingInlineSnapshot(`"TaskRunnerFactory not initialized"`); ).toThrowErrorMatchingInlineSnapshot(`"TaskRunnerFactory not initialized"`);
}); });

View file

@ -28,7 +28,7 @@ import {
import { TaskRunner } from './task_runner'; import { TaskRunner } from './task_runner';
import { IEventLogger } from '../../../event_log/server'; import { IEventLogger } from '../../../event_log/server';
import { RulesClient } from '../rules_client'; import { RulesClient } from '../rules_client';
import { NormalizedAlertType } from '../rule_type_registry'; import { NormalizedRuleType } from '../rule_type_registry';
export interface TaskRunnerContext { export interface TaskRunnerContext {
logger: Logger; logger: Logger;
@ -44,7 +44,7 @@ export interface TaskRunnerContext {
ruleTypeRegistry: RuleTypeRegistry; ruleTypeRegistry: RuleTypeRegistry;
kibanaBaseUrl: string | undefined; kibanaBaseUrl: string | undefined;
supportsEphemeralTasks: boolean; supportsEphemeralTasks: boolean;
maxEphemeralActionsPerAlert: number; maxEphemeralActionsPerRule: number;
cancelAlertsOnRuleTimeout: boolean; cancelAlertsOnRuleTimeout: boolean;
} }
@ -69,7 +69,7 @@ export class TaskRunnerFactory {
ActionGroupIds extends string, ActionGroupIds extends string,
RecoveryActionGroupId extends string RecoveryActionGroupId extends string
>( >(
alertType: NormalizedAlertType< ruleType: NormalizedRuleType<
Params, Params,
ExtractedParams, ExtractedParams,
State, State,
@ -92,6 +92,6 @@ export class TaskRunnerFactory {
InstanceContext, InstanceContext,
ActionGroupIds, ActionGroupIds,
RecoveryActionGroupId RecoveryActionGroupId
>(alertType, taskInstance, this.taskRunnerContext!); >(ruleType, taskInstance, this.taskRunnerContext!);
} }
} }

View file

@ -118,7 +118,7 @@ export type ExecutorType<
export interface AlertTypeParamsValidator<Params extends AlertTypeParams> { export interface AlertTypeParamsValidator<Params extends AlertTypeParams> {
validate: (object: unknown) => Params; validate: (object: unknown) => Params;
} }
export interface AlertType< export interface RuleType<
Params extends AlertTypeParams = never, Params extends AlertTypeParams = never,
ExtractedParams extends AlertTypeParams = never, ExtractedParams extends AlertTypeParams = never,
State extends AlertTypeState = never, State extends AlertTypeState = never,
@ -163,7 +163,7 @@ export interface AlertType<
ruleTaskTimeout?: string; ruleTaskTimeout?: string;
cancelAlertsOnRuleTimeout?: boolean; cancelAlertsOnRuleTimeout?: boolean;
} }
export type UntypedAlertType = AlertType< export type UntypedRuleType = RuleType<
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
AlertInstanceState, AlertInstanceState,
@ -184,7 +184,7 @@ export interface AlertMeta extends SavedObjectAttributes {
// note that the `error` property is "null-able", as we're doing a partial // note that the `error` property is "null-able", as we're doing a partial
// update on the alert when we update this data, but need to ensure we // update on the alert when we update this data, but need to ensure we
// delete any previous error if the current status has no error // delete any previous error if the current status has no error
export interface RawAlertExecutionStatus extends SavedObjectAttributes { export interface RawRuleExecutionStatus extends SavedObjectAttributes {
status: AlertExecutionStatuses; status: AlertExecutionStatuses;
lastExecutionDate: string; lastExecutionDate: string;
lastDuration?: number; lastDuration?: number;
@ -201,7 +201,7 @@ export interface AlertWithLegacyId<Params extends AlertTypeParams = never> exten
legacyId: string | null; legacyId: string | null;
} }
export type SanitizedAlertWithLegacyId<Params extends AlertTypeParams = never> = Omit< export type SanitizedRuleWithLegacyId<Params extends AlertTypeParams = never> = Omit<
AlertWithLegacyId<Params>, AlertWithLegacyId<Params>,
'apiKey' 'apiKey'
>; >;
@ -212,11 +212,11 @@ export type PartialAlertWithLegacyId<Params extends AlertTypeParams = never> = P
> & > &
Partial<Omit<AlertWithLegacyId<Params>, 'id'>>; Partial<Omit<AlertWithLegacyId<Params>, 'id'>>;
export interface RawAlert extends SavedObjectAttributes { export interface RawRule extends SavedObjectAttributes {
enabled: boolean; enabled: boolean;
name: string; name: string;
tags: string[]; tags: string[];
alertTypeId: string; alertTypeId: string; // this cannot be renamed since it is in the saved object
consumer: string; consumer: string;
legacyId: string | null; legacyId: string | null;
schedule: SavedObjectAttributes; schedule: SavedObjectAttributes;
@ -234,11 +234,11 @@ export interface RawAlert extends SavedObjectAttributes {
muteAll: boolean; muteAll: boolean;
mutedInstanceIds: string[]; mutedInstanceIds: string[];
meta?: AlertMeta; meta?: AlertMeta;
executionStatus: RawAlertExecutionStatus; executionStatus: RawRuleExecutionStatus;
} }
export type AlertInfoParams = Pick< export type AlertInfoParams = Pick<
RawAlert, RawRule,
| 'params' | 'params'
| 'throttle' | 'throttle'
| 'notifyWhen' | 'notifyWhen'

View file

@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { MlPluginSetup } from '../../../../../ml/server'; import { MlPluginSetup } from '../../../../../ml/server';
import { import {
AlertType as RuleType, RuleType,
AlertInstanceState as AlertState, AlertInstanceState as AlertState,
AlertInstanceContext as AlertContext, AlertInstanceContext as AlertContext,
} from '../../../../../alerting/server'; } from '../../../../../alerting/server';

View file

@ -8,7 +8,7 @@
import { schema } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { ActionGroupIdsOf } from '../../../../../alerting/common'; import { ActionGroupIdsOf } from '../../../../../alerting/common';
import { AlertType, PluginSetupContract } from '../../../../../alerting/server'; import { RuleType, PluginSetupContract } from '../../../../../alerting/server';
import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api'; import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api';
import { import {
createMetricThresholdExecutor, createMetricThresholdExecutor,
@ -31,7 +31,7 @@ import {
type MetricThresholdAllowedActionGroups = ActionGroupIdsOf< type MetricThresholdAllowedActionGroups = ActionGroupIdsOf<
typeof FIRED_ACTIONS | typeof WARNING_ACTIONS typeof FIRED_ACTIONS | typeof WARNING_ACTIONS
>; >;
export type MetricThresholdAlertType = Omit<AlertType, 'ActionGroupIdsOf'> & { export type MetricThresholdAlertType = Omit<RuleType, 'ActionGroupIdsOf'> & {
ActionGroupIdsOf: MetricThresholdAllowedActionGroups; ActionGroupIdsOf: MetricThresholdAllowedActionGroups;
}; };

View file

@ -8,7 +8,7 @@
import { Logger, ElasticsearchClient } from 'kibana/server'; import { Logger, ElasticsearchClient } from 'kibana/server';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { import {
AlertType, RuleType,
AlertExecutorOptions, AlertExecutorOptions,
AlertInstance, AlertInstance,
RulesClient, RulesClient,
@ -80,7 +80,7 @@ export class BaseRule {
this.scopedLogger = Globals.app.getLogger(ruleOptions.id); this.scopedLogger = Globals.app.getLogger(ruleOptions.id);
} }
public getRuleType(): AlertType<never, never, never, never, never, 'default'> { public getRuleType(): RuleType<never, never, never, never, never, 'default'> {
const { id, name, actionVariables } = this.ruleOptions; const { id, name, actionVariables } = this.ruleOptions;
return { return {
id, id,

View file

@ -12,14 +12,14 @@ import {
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
} from '../../alerting/common'; } from '../../alerting/common';
import { AlertExecutorOptions, AlertServices, AlertType } from '../../alerting/server'; import { AlertExecutorOptions, AlertServices, RuleType } from '../../alerting/server';
import { AlertsClient } from './alert_data_client/alerts_client'; import { AlertsClient } from './alert_data_client/alerts_client';
type SimpleAlertType< type SimpleAlertType<
TState extends AlertTypeState, TState extends AlertTypeState,
TParams extends AlertTypeParams = {}, TParams extends AlertTypeParams = {},
TAlertInstanceContext extends AlertInstanceContext = {} TAlertInstanceContext extends AlertInstanceContext = {}
> = AlertType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>; > = RuleType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>;
export type AlertTypeExecutor< export type AlertTypeExecutor<
TState extends AlertTypeState, TState extends AlertTypeState,
@ -38,7 +38,7 @@ export type AlertTypeWithExecutor<
TAlertInstanceContext extends AlertInstanceContext = {}, TAlertInstanceContext extends AlertInstanceContext = {},
TServices extends Record<string, any> = {} TServices extends Record<string, any> = {}
> = Omit< > = Omit<
AlertType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>, RuleType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>,
'executor' 'executor'
> & { > & {
executor: AlertTypeExecutor<TState, TParams, TAlertInstanceContext, TServices>; executor: AlertTypeExecutor<TState, TParams, TAlertInstanceContext, TServices>;

View file

@ -10,7 +10,7 @@ import {
AlertExecutorOptions, AlertExecutorOptions,
AlertInstanceContext, AlertInstanceContext,
AlertInstanceState, AlertInstanceState,
AlertType, RuleType,
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
} from '../../../alerting/server'; } from '../../../alerting/server';
@ -39,7 +39,7 @@ export type PersistenceAlertType<
TInstanceContext extends AlertInstanceContext = {}, TInstanceContext extends AlertInstanceContext = {},
TActionGroupIds extends string = never TActionGroupIds extends string = never
> = Omit< > = Omit<
AlertType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>, RuleType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>,
'executor' 'executor'
> & { > & {
executor: ( executor: (
@ -65,4 +65,4 @@ export type CreatePersistenceRuleTypeWrapper = (options: {
TActionGroupIds extends string = never TActionGroupIds extends string = never
>( >(
type: PersistenceAlertType<TParams, TState, TInstanceContext, TActionGroupIds> type: PersistenceAlertType<TParams, TState, TInstanceContext, TActionGroupIds>
) => AlertType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>; ) => RuleType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>;

View file

@ -10,7 +10,7 @@ import { schema, TypeOf } from '@kbn/config-schema';
import { import {
RulesClient, RulesClient,
PartialAlert, PartialAlert,
AlertType, RuleType,
AlertTypeParams, AlertTypeParams,
AlertTypeState, AlertTypeState,
AlertInstanceState, AlertInstanceState,
@ -103,7 +103,7 @@ export type LegacyNotificationExecutorOptions = AlertExecutorOptions<
*/ */
export const legacyIsNotificationAlertExecutor = ( export const legacyIsNotificationAlertExecutor = (
obj: LegacyNotificationAlertTypeDefinition obj: LegacyNotificationAlertTypeDefinition
): obj is AlertType< ): obj is RuleType<
LegacyRuleNotificationAlertTypeParams, LegacyRuleNotificationAlertTypeParams,
LegacyRuleNotificationAlertTypeParams, LegacyRuleNotificationAlertTypeParams,
AlertTypeState, AlertTypeState,
@ -117,7 +117,7 @@ export const legacyIsNotificationAlertExecutor = (
* @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function
*/ */
export type LegacyNotificationAlertTypeDefinition = Omit< export type LegacyNotificationAlertTypeDefinition = Omit<
AlertType< RuleType<
LegacyRuleNotificationAlertTypeParams, LegacyRuleNotificationAlertTypeParams,
LegacyRuleNotificationAlertTypeParams, LegacyRuleNotificationAlertTypeParams,
AlertTypeState, AlertTypeState,

View file

@ -11,7 +11,7 @@ import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { Logger } from '@kbn/logging'; import { Logger } from '@kbn/logging';
import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import { AlertExecutorOptions, AlertType } from '../../../../../alerting/server'; import { AlertExecutorOptions, RuleType } from '../../../../../alerting/server';
import { import {
AlertInstanceContext, AlertInstanceContext,
AlertInstanceState, AlertInstanceState,
@ -73,7 +73,7 @@ export type SecurityAlertType<
TInstanceContext extends AlertInstanceContext = {}, TInstanceContext extends AlertInstanceContext = {},
TActionGroupIds extends string = never TActionGroupIds extends string = never
> = Omit< > = Omit<
AlertType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>, RuleType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>,
'executor' 'executor'
> & { > & {
executor: ( executor: (
@ -107,7 +107,7 @@ export type CreateSecurityRuleTypeWrapper = (
TInstanceContext extends AlertInstanceContext = {} TInstanceContext extends AlertInstanceContext = {}
>( >(
type: SecurityAlertType<TParams, TState, TInstanceContext, 'default'> type: SecurityAlertType<TParams, TState, TInstanceContext, 'default'>
) => AlertType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, 'default'>; ) => RuleType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, 'default'>;
export type RACAlertSignal = TypeOfFieldMap<AlertsFieldMap> & TypeOfFieldMap<RulesFieldMap>; export type RACAlertSignal = TypeOfFieldMap<AlertsFieldMap> & TypeOfFieldMap<RulesFieldMap>;
export type RACAlert = Exclude< export type RACAlert = Exclude<

View file

@ -12,7 +12,7 @@ import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-t
import { Status } from '../../../../common/detection_engine/schemas/common/schemas'; import { Status } from '../../../../common/detection_engine/schemas/common/schemas';
import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema';
import { import {
AlertType, RuleType,
AlertTypeState, AlertTypeState,
AlertInstanceState, AlertInstanceState,
AlertInstanceContext, AlertInstanceContext,
@ -196,7 +196,7 @@ export type RuleExecutorOptions = AlertExecutorOptions<
// since we are only increasing the strictness of params. // since we are only increasing the strictness of params.
export const isAlertExecutor = ( export const isAlertExecutor = (
obj: SignalRuleAlertTypeDefinition obj: SignalRuleAlertTypeDefinition
): obj is AlertType< ): obj is RuleType<
RuleParams, RuleParams,
RuleParams, // This type is used for useSavedObjectReferences, use an Omit here if you want to remove any values. RuleParams, // This type is used for useSavedObjectReferences, use an Omit here if you want to remove any values.
AlertTypeState, AlertTypeState,
@ -207,7 +207,7 @@ export const isAlertExecutor = (
return true; return true;
}; };
export type SignalRuleAlertTypeDefinition = AlertType< export type SignalRuleAlertTypeDefinition = RuleType<
RuleParams, RuleParams,
RuleParams, // This type is used for useSavedObjectReferences, use an Omit here if you want to remove any values. RuleParams, // This type is used for useSavedObjectReferences, use an Omit here if you want to remove any values.
AlertTypeState, AlertTypeState,

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { Logger } from 'src/core/server'; import { Logger } from 'src/core/server';
import { AlertType, AlertExecutorOptions } from '../../types'; import { RuleType, AlertExecutorOptions } from '../../types';
import { ActionContext, EsQueryAlertActionContext, addMessages } from './action_context'; import { ActionContext, EsQueryAlertActionContext, addMessages } from './action_context';
import { import {
EsQueryAlertParams, EsQueryAlertParams,
@ -25,7 +25,7 @@ export const ES_QUERY_ID = '.es-query';
export const ActionGroupId = 'query matched'; export const ActionGroupId = 'query matched';
export const ConditionMetAlertInstanceId = 'query matched'; export const ConditionMetAlertInstanceId = 'query matched';
export function getAlertType(logger: Logger): AlertType< export function getAlertType(logger: Logger): RuleType<
EsQueryAlertParams, EsQueryAlertParams,
never, // Only use if defining useSavedObjectReferences hook never, // Only use if defining useSavedObjectReferences hook
EsQueryAlertState, EsQueryAlertState,

View file

@ -11,7 +11,7 @@ import { Logger, SavedObjectReference } from 'src/core/server';
import { STACK_ALERTS_FEATURE_ID } from '../../../common'; import { STACK_ALERTS_FEATURE_ID } from '../../../common';
import { getGeoContainmentExecutor } from './geo_containment'; import { getGeoContainmentExecutor } from './geo_containment';
import { import {
AlertType, RuleType,
AlertTypeState, AlertTypeState,
AlertInstanceState, AlertInstanceState,
AlertInstanceContext, AlertInstanceContext,
@ -147,7 +147,7 @@ export interface GeoContainmentInstanceContext extends AlertInstanceContext {
containingBoundaryName: unknown; containingBoundaryName: unknown;
} }
export type GeoContainmentAlertType = AlertType< export type GeoContainmentAlertType = RuleType<
GeoContainmentParams, GeoContainmentParams,
GeoContainmentExtractedParams, GeoContainmentExtractedParams,
GeoContainmentState, GeoContainmentState,

View file

@ -7,7 +7,7 @@
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { Logger } from 'src/core/server'; import { Logger } from 'src/core/server';
import { AlertType, AlertExecutorOptions, StackAlertsStartDeps } from '../../types'; import { RuleType, AlertExecutorOptions, StackAlertsStartDeps } from '../../types';
import { Params, ParamsSchema } from './alert_type_params'; import { Params, ParamsSchema } from './alert_type_params';
import { ActionContext, BaseActionContext, addMessages } from './action_context'; import { ActionContext, BaseActionContext, addMessages } from './action_context';
import { STACK_ALERTS_FEATURE_ID } from '../../../common'; import { STACK_ALERTS_FEATURE_ID } from '../../../common';
@ -23,7 +23,7 @@ export const ActionGroupId = 'threshold met';
export function getAlertType( export function getAlertType(
logger: Logger, logger: Logger,
data: Promise<StackAlertsStartDeps['triggersActionsUi']['data']> data: Promise<StackAlertsStartDeps['triggersActionsUi']['data']>
): AlertType<Params, never, {}, {}, ActionContext, typeof ActionGroupId> { ): RuleType<Params, never, {}, {}, ActionContext, typeof ActionGroupId> {
const alertTypeName = i18n.translate('xpack.stackAlerts.indexThreshold.alertTypeTitle', { const alertTypeName = i18n.translate('xpack.stackAlerts.indexThreshold.alertTypeTitle', {
defaultMessage: 'Index threshold', defaultMessage: 'Index threshold',
}); });

View file

@ -10,7 +10,7 @@ import { PluginSetupContract as AlertingSetup } from '../../alerting/server';
export type { export type {
PluginSetupContract as AlertingSetup, PluginSetupContract as AlertingSetup,
AlertType, RuleType,
RuleParamsAndRefs, RuleParamsAndRefs,
AlertExecutorOptions, AlertExecutorOptions,
} from '../../alerting/server'; } from '../../alerting/server';

View file

@ -15,7 +15,7 @@ import type {
} from '../../../../../alerting/common'; } from '../../../../../alerting/common';
import { PLUGIN, TRANSFORM_RULE_TYPE } from '../../../../common/constants'; import { PLUGIN, TRANSFORM_RULE_TYPE } from '../../../../common/constants';
import { transformHealthRuleParams, TransformHealthRuleParams } from './schema'; import { transformHealthRuleParams, TransformHealthRuleParams } from './schema';
import { AlertType } from '../../../../../alerting/server'; import { RuleType } from '../../../../../alerting/server';
import { transformHealthServiceProvider } from './transform_health_service'; import { transformHealthServiceProvider } from './transform_health_service';
import type { PluginSetupContract as AlertingSetup } from '../../../../../alerting/server'; import type { PluginSetupContract as AlertingSetup } from '../../../../../alerting/server';
@ -57,7 +57,7 @@ export function registerTransformHealthRuleType(params: RegisterParams) {
alerting.registerType(getTransformHealthRuleType()); alerting.registerType(getTransformHealthRuleType());
} }
export function getTransformHealthRuleType(): AlertType< export function getTransformHealthRuleType(): RuleType<
TransformHealthRuleParams, TransformHealthRuleParams,
never, never,
AlertTypeState, AlertTypeState,

View file

@ -5343,16 +5343,16 @@
"xpack.alerting.rulesClient.invalidDate": "パラメーター{field}の無効な日付:「{dateValue}」", "xpack.alerting.rulesClient.invalidDate": "パラメーター{field}の無効な日付:「{dateValue}」",
"xpack.alerting.rulesClient.validateActions.invalidGroups": "無効なアクショングループ:{groups}", "xpack.alerting.rulesClient.validateActions.invalidGroups": "無効なアクショングループ:{groups}",
"xpack.alerting.rulesClient.validateActions.misconfiguredConnector": "無効なコネクター:{groups}", "xpack.alerting.rulesClient.validateActions.misconfiguredConnector": "無効なコネクター:{groups}",
"xpack.alerting.ruleTypeRegistry.get.missingAlertTypeError": "ルールタイプ「{id}」は登録されていません。", "xpack.alerting.ruleTypeRegistry.get.missingRuleTypeError": "ルールタイプ「{id}」は登録されていません。",
"xpack.alerting.ruleTypeRegistry.register.customRecoveryActionGroupUsageError": "ルールタイプ[id=\"{id}\"]を登録できません。アクショングループ [{actionGroup}] は、復元とアクティブなアクショングループの両方として使用できません。", "xpack.alerting.ruleTypeRegistry.register.customRecoveryActionGroupUsageError": "ルールタイプ[id=\"{id}\"]を登録できません。アクショングループ [{actionGroup}] は、復元とアクティブなアクショングループの両方として使用できません。",
"xpack.alerting.ruleTypeRegistry.register.duplicateAlertTypeError": "ルールタイプ\"{id}\"はすでに登録されています。", "xpack.alerting.ruleTypeRegistry.register.duplicateRuleTypeError": "ルールタイプ\"{id}\"はすでに登録されています。",
"xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutAlertTypeError": "ルールタイプ\"{id}\"のデフォルト間隔が無効です:{errorMessage}。", "xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutRuleTypeError": "ルールタイプ\"{id}\"のデフォルト間隔が無効です:{errorMessage}。",
"xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutAlertTypeError": "ルールタイプ\"{id}\"の最低間隔が無効です:{errorMessage}。", "xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutRuleTypeError": "ルールタイプ\"{id}\"の最低間隔が無効です:{errorMessage}。",
"xpack.alerting.ruleTypeRegistry.register.invalidTimeoutAlertTypeError": "ルールタイプ\"{id}\"のタイムアウトが無効です:{errorMessage}。", "xpack.alerting.ruleTypeRegistry.register.invalidTimeoutRuleTypeError": "ルールタイプ\"{id}\"のタイムアウトが無効です:{errorMessage}。",
"xpack.alerting.savedObjects.goToRulesButtonText": "ルールに移動", "xpack.alerting.savedObjects.goToRulesButtonText": "ルールに移動",
"xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "{licenseType} ライセンスの期限が切れたのでアラートタイプ {alertTypeId} は無効です。", "xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "{licenseType} ライセンスの期限が切れたのでアラートタイプ {ruleTypeId} は無効です。",
"xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "アラート{alertTypeId}は無効です。{licenseType}ライセンスが必要です。アップグレードオプションを表示するには、[ライセンス管理]に移動してください。", "xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "アラート{ruleTypeId}は無効です。{licenseType}ライセンスが必要です。アップグレードオプションを表示するには、[ライセンス管理]に移動してください。",
"xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "現時点でライセンス情報を入手できないため、アラートタイプ {alertTypeId} は無効です。", "xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "現時点でライセンス情報を入手できないため、アラートタイプ {ruleTypeId} は無効です。",
"xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "アラートを利用できません。現在ライセンス情報が利用できません。", "xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "アラートを利用できません。現在ライセンス情報が利用できません。",
"xpack.apm.a.thresholdMet": "しきい値一致", "xpack.apm.a.thresholdMet": "しきい値一致",
"xpack.apm.addDataButtonLabel": "データの追加", "xpack.apm.addDataButtonLabel": "データの追加",

View file

@ -5378,18 +5378,18 @@
"xpack.alerting.rulesClient.invalidDate": "参数 {field} 的日期无效:“{dateValue}”", "xpack.alerting.rulesClient.invalidDate": "参数 {field} 的日期无效:“{dateValue}”",
"xpack.alerting.rulesClient.validateActions.invalidGroups": "无效操作组:{groups}", "xpack.alerting.rulesClient.validateActions.invalidGroups": "无效操作组:{groups}",
"xpack.alerting.rulesClient.validateActions.misconfiguredConnector": "无效的连接器:{groups}", "xpack.alerting.rulesClient.validateActions.misconfiguredConnector": "无效的连接器:{groups}",
"xpack.alerting.ruleTypeRegistry.get.missingAlertTypeError": "未注册规则类型“{id}”。", "xpack.alerting.ruleTypeRegistry.get.missingRuleTypeError": "未注册规则类型“{id}”。",
"xpack.alerting.ruleTypeRegistry.register.customRecoveryActionGroupUsageError": "无法注册规则类型 [id=\"{id}\"]。操作组 [{actionGroup}] 无法同时用作恢复和活动操作组。", "xpack.alerting.ruleTypeRegistry.register.customRecoveryActionGroupUsageError": "无法注册规则类型 [id=\"{id}\"]。操作组 [{actionGroup}] 无法同时用作恢复和活动操作组。",
"xpack.alerting.ruleTypeRegistry.register.duplicateAlertTypeError": "已注册规则类型“{id}”。", "xpack.alerting.ruleTypeRegistry.register.duplicateRuleTypeError": "已注册规则类型“{id}”。",
"xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutAlertTypeError": "规则类型“{id}”的默认时间间隔无效:{errorMessage}。", "xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutRuleTypeError": "规则类型“{id}”的默认时间间隔无效:{errorMessage}。",
"xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutAlertTypeError": "规则类型“{id}”的最小时间间隔无效:{errorMessage}。", "xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutRuleTypeError": "规则类型“{id}”的最小时间间隔无效:{errorMessage}。",
"xpack.alerting.ruleTypeRegistry.register.invalidTimeoutAlertTypeError": "规则类型“{id}”的超时无效:{errorMessage}。", "xpack.alerting.ruleTypeRegistry.register.invalidTimeoutRuleTypeError": "规则类型“{id}”的超时无效:{errorMessage}。",
"xpack.alerting.ruleTypeRegistry.register.reservedActionGroupUsageError": "无法注册规则类型 [id=\"{id}\"]。操作组 [{actionGroups}] 由框架保留。", "xpack.alerting.ruleTypeRegistry.register.reservedActionGroupUsageError": "无法注册规则类型 [id=\"{id}\"]。操作组 [{actionGroups}] 由框架保留。",
"xpack.alerting.savedObjects.goToRulesButtonText": "前往规则", "xpack.alerting.savedObjects.goToRulesButtonText": "前往规则",
"xpack.alerting.savedObjects.onImportText": "导入后必须启用 {rulesSavedObjectsLength} 个{rulesSavedObjectsLength, plural,other {规则}}。", "xpack.alerting.savedObjects.onImportText": "导入后必须启用 {rulesSavedObjectsLength} 个{rulesSavedObjectsLength, plural,other {规则}}。",
"xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "告警类型 {alertTypeId} 已禁用,因为您的{licenseType}许可证已过期。", "xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "告警类型 {ruleTypeId} 已禁用,因为您的{licenseType}许可证已过期。",
"xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "告警 {alertTypeId} 已禁用,因为它需要{licenseType}许可证。前往“许可证管理”以查看升级选项。", "xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "告警 {ruleTypeId} 已禁用,因为它需要{licenseType}许可证。前往“许可证管理”以查看升级选项。",
"xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "告警类型 {alertTypeId} 已禁用,因为许可证信息当前不可用。", "xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "告警类型 {ruleTypeId} 已禁用,因为许可证信息当前不可用。",
"xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "告警不可用 - 许可信息当前不可用。", "xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "告警不可用 - 许可信息当前不可用。",
"xpack.apm.a.thresholdMet": "已达到阈值", "xpack.apm.a.thresholdMet": "已达到阈值",
"xpack.apm.addDataButtonLabel": "添加数据", "xpack.apm.addDataButtonLabel": "添加数据",

View file

@ -8,12 +8,12 @@ import { HttpSetup } from 'kibana/public';
import { pipe } from 'fp-ts/lib/pipeable'; import { pipe } from 'fp-ts/lib/pipeable';
import { fold } from 'fp-ts/lib/Either'; import { fold } from 'fp-ts/lib/Either';
import { Errors, identity } from 'io-ts'; import { Errors, identity } from 'io-ts';
import { AlertTaskState } from '../../../types'; import { RuleTaskState } from '../../../types';
import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants';
import { alertStateSchema } from '../../../../../alerting/common'; import { ruleStateSchema } from '../../../../../alerting/common';
import { AsApiContract, RewriteRequestCase } from '../../../../../actions/common'; import { AsApiContract, RewriteRequestCase } from '../../../../../actions/common';
const rewriteBodyRes: RewriteRequestCase<AlertTaskState> = ({ const rewriteBodyRes: RewriteRequestCase<RuleTaskState> = ({
rule_type_state: alertTypeState, rule_type_state: alertTypeState,
alerts: alertInstances, alerts: alertInstances,
previous_started_at: previousStartedAt, previous_started_at: previousStartedAt,
@ -32,17 +32,17 @@ export async function loadAlertState({
}: { }: {
http: HttpSetup; http: HttpSetup;
alertId: string; alertId: string;
}): Promise<AlertTaskState> { }): Promise<RuleTaskState> {
return await http return await http
.get<AsApiContract<AlertTaskState> | EmptyHttpResponse>( .get<AsApiContract<RuleTaskState> | EmptyHttpResponse>(
`${INTERNAL_BASE_ALERTING_API_PATH}/rule/${alertId}/state` `${INTERNAL_BASE_ALERTING_API_PATH}/rule/${alertId}/state`
) )
.then((state) => (state ? rewriteBodyRes(state) : {})) .then((state) => (state ? rewriteBodyRes(state) : {}))
.then((state: AlertTaskState) => { .then((state: RuleTaskState) => {
return pipe( return pipe(
alertStateSchema.decode(state), ruleStateSchema.decode(state),
fold((e: Errors) => { fold((e: Errors) => {
throw new Error(`Alert "${alertId}" has invalid state`); throw new Error(`Rule "${alertId}" has invalid state`);
}, identity) }, identity)
); );
}); });

View file

@ -10,7 +10,7 @@ import React from 'react';
import { import {
Alert, Alert,
AlertType, AlertType,
AlertTaskState, RuleTaskState,
AlertSummary, AlertSummary,
AlertingFrameworkHealth, AlertingFrameworkHealth,
ResolvedRule, ResolvedRule,
@ -56,7 +56,7 @@ export interface ComponentOpts {
errors: string[]; errors: string[];
}>; }>;
loadAlert: (id: Alert['id']) => Promise<Alert>; loadAlert: (id: Alert['id']) => Promise<Alert>;
loadAlertState: (id: Alert['id']) => Promise<AlertTaskState>; loadAlertState: (id: Alert['id']) => Promise<RuleTaskState>;
loadAlertSummary: (id: Alert['id']) => Promise<AlertSummary>; loadAlertSummary: (id: Alert['id']) => Promise<AlertSummary>;
loadAlertTypes: () => Promise<AlertType[]>; loadAlertTypes: () => Promise<AlertType[]>;
getHealth: () => Promise<AlertingFrameworkHealth>; getHealth: () => Promise<AlertingFrameworkHealth>;

View file

@ -27,7 +27,7 @@ import {
ResolvedSanitizedRule, ResolvedSanitizedRule,
AlertAction, AlertAction,
AlertAggregations, AlertAggregations,
AlertTaskState, RuleTaskState,
AlertSummary, AlertSummary,
ExecutionDuration, ExecutionDuration,
AlertStatus, AlertStatus,
@ -36,7 +36,7 @@ import {
AlertNotifyWhenType, AlertNotifyWhenType,
AlertTypeParams, AlertTypeParams,
ActionVariable, ActionVariable,
AlertType as CommonAlertType, RuleType as CommonRuleType,
} from '../../alerting/common'; } from '../../alerting/common';
// In Triggers and Actions we treat all `Alert`s as `SanitizedAlert<AlertTypeParams>` // In Triggers and Actions we treat all `Alert`s as `SanitizedAlert<AlertTypeParams>`
@ -48,7 +48,7 @@ export type {
Alert, Alert,
AlertAction, AlertAction,
AlertAggregations, AlertAggregations,
AlertTaskState, RuleTaskState,
AlertSummary, AlertSummary,
ExecutionDuration, ExecutionDuration,
AlertStatus, AlertStatus,
@ -208,7 +208,7 @@ export interface AlertType<
ActionGroupIds extends string = string, ActionGroupIds extends string = string,
RecoveryActionGroupId extends string = string RecoveryActionGroupId extends string = string
> extends Pick< > extends Pick<
CommonAlertType<ActionGroupIds, RecoveryActionGroupId>, CommonRuleType<ActionGroupIds, RecoveryActionGroupId>,
| 'id' | 'id'
| 'name' | 'name'
| 'actionGroups' | 'actionGroups'

View file

@ -22,7 +22,7 @@ export default function emailTest({ getService }: FtrProviderContext) {
statusCode: 403, statusCode: 403,
error: 'Forbidden', error: 'Forbidden',
message: message:
'Alert test.gold.noop is disabled because it requires a Gold license. Go to License Management to view upgrade options.', 'Rule test.gold.noop is disabled because it requires a Gold license. Go to License Management to view upgrade options.',
}); });
}); });
}); });

View file

@ -11,7 +11,7 @@ import { curry, times } from 'lodash';
import { ES_TEST_INDEX_NAME } from '../../../../lib'; import { ES_TEST_INDEX_NAME } from '../../../../lib';
import { FixtureStartDeps, FixtureSetupDeps } from './plugin'; import { FixtureStartDeps, FixtureSetupDeps } from './plugin';
import { import {
AlertType, RuleType,
AlertInstanceState, AlertInstanceState,
AlertInstanceContext, AlertInstanceContext,
AlertTypeState, AlertTypeState,
@ -62,7 +62,7 @@ function getAlwaysFiringAlertType() {
interface InstanceContext extends AlertInstanceContext { interface InstanceContext extends AlertInstanceContext {
instanceContextValue: boolean; instanceContextValue: boolean;
} }
const result: AlertType< const result: RuleType<
ParamsType & AlertTypeParams, ParamsType & AlertTypeParams,
never, // Only use if defining useSavedObjectReferences hook never, // Only use if defining useSavedObjectReferences hook
State, State,
@ -159,7 +159,7 @@ function getCumulativeFiringAlertType() {
interface InstanceState extends AlertInstanceState { interface InstanceState extends AlertInstanceState {
instanceStateValue: boolean; instanceStateValue: boolean;
} }
const result: AlertType<{}, {}, State, InstanceState, {}, 'default' | 'other'> = { const result: RuleType<{}, {}, State, InstanceState, {}, 'default' | 'other'> = {
id: 'test.cumulative-firing', id: 'test.cumulative-firing',
name: 'Test: Cumulative Firing', name: 'Test: Cumulative Firing',
actionGroups: [ actionGroups: [
@ -200,7 +200,7 @@ function getNeverFiringAlertType() {
interface State extends AlertTypeState { interface State extends AlertTypeState {
globalStateValue: boolean; globalStateValue: boolean;
} }
const result: AlertType<ParamsType, never, State, {}, {}, 'default'> = { const result: RuleType<ParamsType, never, State, {}, {}, 'default'> = {
id: 'test.never-firing', id: 'test.never-firing',
name: 'Test: Never firing', name: 'Test: Never firing',
actionGroups: [ actionGroups: [
@ -241,7 +241,7 @@ function getFailingAlertType() {
reference: schema.string(), reference: schema.string(),
}); });
type ParamsType = TypeOf<typeof paramsSchema>; type ParamsType = TypeOf<typeof paramsSchema>;
const result: AlertType<ParamsType, never, {}, {}, {}, 'default'> = { const result: RuleType<ParamsType, never, {}, {}, {}, 'default'> = {
id: 'test.failing', id: 'test.failing',
name: 'Test: Failing', name: 'Test: Failing',
validate: { validate: {
@ -283,7 +283,7 @@ function getAuthorizationAlertType(core: CoreSetup<FixtureStartDeps>) {
reference: schema.string(), reference: schema.string(),
}); });
type ParamsType = TypeOf<typeof paramsSchema>; type ParamsType = TypeOf<typeof paramsSchema>;
const result: AlertType<ParamsType, never, {}, {}, {}, 'default'> = { const result: RuleType<ParamsType, never, {}, {}, {}, 'default'> = {
id: 'test.authorization', id: 'test.authorization',
name: 'Test: Authorization', name: 'Test: Authorization',
actionGroups: [ actionGroups: [
@ -371,7 +371,7 @@ function getValidationAlertType() {
param1: schema.string(), param1: schema.string(),
}); });
type ParamsType = TypeOf<typeof paramsSchema>; type ParamsType = TypeOf<typeof paramsSchema>;
const result: AlertType<ParamsType, never, {}, {}, {}, 'default'> = { const result: RuleType<ParamsType, never, {}, {}, {}, 'default'> = {
id: 'test.validation', id: 'test.validation',
name: 'Test: Validation', name: 'Test: Validation',
actionGroups: [ actionGroups: [
@ -404,7 +404,7 @@ function getPatternFiringAlertType() {
interface State extends AlertTypeState { interface State extends AlertTypeState {
patternIndex?: number; patternIndex?: number;
} }
const result: AlertType<ParamsType, never, State, {}, {}, 'default'> = { const result: RuleType<ParamsType, never, State, {}, {}, 'default'> = {
id: 'test.patternFiring', id: 'test.patternFiring',
name: 'Test: Firing on a Pattern', name: 'Test: Firing on a Pattern',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -473,7 +473,7 @@ function getLongRunningPatternRuleType(cancelAlertsOnRuleTimeout: boolean = true
interface State extends AlertTypeState { interface State extends AlertTypeState {
patternIndex?: number; patternIndex?: number;
} }
const result: AlertType<ParamsType, never, State, {}, {}, 'default'> = { const result: RuleType<ParamsType, never, State, {}, {}, 'default'> = {
id: `test.patternLongRunning${ id: `test.patternLongRunning${
cancelAlertsOnRuleTimeout === true ? '.cancelAlertsOnRuleTimeout' : '' cancelAlertsOnRuleTimeout === true ? '.cancelAlertsOnRuleTimeout' : ''
}`, }`,
@ -519,7 +519,7 @@ export function defineAlertTypes(
core: CoreSetup<FixtureStartDeps>, core: CoreSetup<FixtureStartDeps>,
{ alerting }: Pick<FixtureSetupDeps, 'alerting'> { alerting }: Pick<FixtureSetupDeps, 'alerting'>
) { ) {
const noopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { const noopAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.noop', id: 'test.noop',
name: 'Test: Noop', name: 'Test: Noop',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -529,7 +529,7 @@ export function defineAlertTypes(
isExportable: true, isExportable: true,
async executor() {}, async executor() {},
}; };
const goldNoopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { const goldNoopAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.gold.noop', id: 'test.gold.noop',
name: 'Test: Noop', name: 'Test: Noop',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -539,7 +539,7 @@ export function defineAlertTypes(
isExportable: true, isExportable: true,
async executor() {}, async executor() {},
}; };
const onlyContextVariablesAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { const onlyContextVariablesAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.onlyContextVariables', id: 'test.onlyContextVariables',
name: 'Test: Only Context Variables', name: 'Test: Only Context Variables',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -552,7 +552,7 @@ export function defineAlertTypes(
}, },
async executor() {}, async executor() {},
}; };
const onlyStateVariablesAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { const onlyStateVariablesAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.onlyStateVariables', id: 'test.onlyStateVariables',
name: 'Test: Only State Variables', name: 'Test: Only State Variables',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -565,7 +565,7 @@ export function defineAlertTypes(
isExportable: true, isExportable: true,
async executor() {}, async executor() {},
}; };
const throwAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { const throwAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.throw', id: 'test.throw',
name: 'Test: Throw', name: 'Test: Throw',
actionGroups: [ actionGroups: [
@ -582,7 +582,7 @@ export function defineAlertTypes(
throw new Error('this alert is intended to fail'); throw new Error('this alert is intended to fail');
}, },
}; };
const longRunningAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { const longRunningAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.longRunning', id: 'test.longRunning',
name: 'Test: Long Running', name: 'Test: Long Running',
actionGroups: [ actionGroups: [
@ -599,8 +599,7 @@ export function defineAlertTypes(
await new Promise((resolve) => setTimeout(resolve, 5000)); await new Promise((resolve) => setTimeout(resolve, 5000));
}, },
}; };
const exampleAlwaysFiringAlertType: AlertType<{}, {}, {}, {}, {}, 'small' | 'medium' | 'large'> = const exampleAlwaysFiringAlertType: RuleType<{}, {}, {}, {}, {}, 'small' | 'medium' | 'large'> = {
{
id: 'example.always-firing', id: 'example.always-firing',
name: 'Always firing', name: 'Always firing',
actionGroups: [ actionGroups: [

View file

@ -16,7 +16,7 @@ import {
} from 'kibana/server'; } from 'kibana/server';
import { schema } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema';
import { InvalidatePendingApiKey } from '../../../../../../../plugins/alerting/server/types'; import { InvalidatePendingApiKey } from '../../../../../../../plugins/alerting/server/types';
import { RawAlert } from '../../../../../../../plugins/alerting/server/types'; import { RawRule } from '../../../../../../../plugins/alerting/server/types';
import { import {
ConcreteTaskInstance, ConcreteTaskInstance,
TaskInstance, TaskInstance,
@ -89,12 +89,12 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo
logger, logger,
`/api/alerts_fixture/${id}/replace_api_key`, `/api/alerts_fixture/${id}/replace_api_key`,
async () => { async () => {
return await savedObjectsWithAlerts.update<RawAlert>( return await savedObjectsWithAlerts.update<RawRule>(
'alert', 'alert',
id, id,
{ {
...( ...(
await encryptedSavedObjectsWithAlerts.getDecryptedAsInternalUser<RawAlert>( await encryptedSavedObjectsWithAlerts.getDecryptedAsInternalUser<RawRule>(
'alert', 'alert',
id, id,
{ {
@ -154,7 +154,7 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo
const savedObjectsWithAlerts = await savedObjects.getScopedClient(req, { const savedObjectsWithAlerts = await savedObjects.getScopedClient(req, {
includedHiddenTypes: ['alert'], includedHiddenTypes: ['alert'],
}); });
const savedAlert = await savedObjectsWithAlerts.get<RawAlert>(type, id); const savedAlert = await savedObjectsWithAlerts.get<RawRule>(type, id);
const result = await retryIfConflicts( const result = await retryIfConflicts(
logger, logger,
`/api/alerts_fixture/saved_object/${type}/${id}`, `/api/alerts_fixture/saved_object/${type}/${id}`,
@ -232,7 +232,7 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo
const savedObjectsWithTasksAndAlerts = await savedObjects.getScopedClient(req, { const savedObjectsWithTasksAndAlerts = await savedObjects.getScopedClient(req, {
includedHiddenTypes: ['task', 'alert'], includedHiddenTypes: ['task', 'alert'],
}); });
const alert = await savedObjectsWithTasksAndAlerts.get<RawAlert>('alert', id); const alert = await savedObjectsWithTasksAndAlerts.get<RawRule>('alert', id);
const result = await retryIfConflicts( const result = await retryIfConflicts(
logger, logger,
`/api/alerts_fixture/{id}/reset_task_status`, `/api/alerts_fixture/{id}/reset_task_status`,

View file

@ -7,13 +7,13 @@
import { CoreSetup } from 'src/core/server'; import { CoreSetup } from 'src/core/server';
import { FixtureStartDeps, FixtureSetupDeps } from './plugin'; import { FixtureStartDeps, FixtureSetupDeps } from './plugin';
import { AlertType } from '../../../../../../../plugins/alerting/server'; import { RuleType } from '../../../../../../../plugins/alerting/server';
export function defineAlertTypes( export function defineAlertTypes(
core: CoreSetup<FixtureStartDeps>, core: CoreSetup<FixtureStartDeps>,
{ alerting }: Pick<FixtureSetupDeps, 'alerting'> { alerting }: Pick<FixtureSetupDeps, 'alerting'>
) { ) {
const noopRestrictedAlertType: AlertType<{}, {}, {}, {}, {}, 'default', 'restrictedRecovered'> = { const noopRestrictedAlertType: RuleType<{}, {}, {}, {}, {}, 'default', 'restrictedRecovered'> = {
id: 'test.restricted-noop', id: 'test.restricted-noop',
name: 'Test: Restricted Noop', name: 'Test: Restricted Noop',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -24,7 +24,7 @@ export function defineAlertTypes(
recoveryActionGroup: { id: 'restrictedRecovered', name: 'Restricted Recovery' }, recoveryActionGroup: { id: 'restrictedRecovered', name: 'Restricted Recovery' },
async executor() {}, async executor() {},
}; };
const noopUnrestrictedAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { const noopUnrestrictedAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.unrestricted-noop', id: 'test.unrestricted-noop',
name: 'Test: Unrestricted Noop', name: 'Test: Unrestricted Noop',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],

View file

@ -227,7 +227,7 @@ instanceStateValue: true
alertId, alertId,
ruleTypeId: 'test.always-firing', ruleTypeId: 'test.always-firing',
outcome: 'success', outcome: 'success',
message: `alert executed: test.always-firing:${alertId}: 'abc'`, message: `rule executed: test.always-firing:${alertId}: 'abc'`,
ruleObject: alertSearchResultWithoutDates, ruleObject: alertSearchResultWithoutDates,
}); });
break; break;

View file

@ -17,7 +17,7 @@ import {
TaskManagerDoc, TaskManagerDoc,
} from '../../../common/lib'; } from '../../../common/lib';
import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { RawAlert } from '../../../../../plugins/alerting/server/types'; import { RawRule } from '../../../../../plugins/alerting/server/types';
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
export default function createAlertTests({ getService }: FtrProviderContext) { export default function createAlertTests({ getService }: FtrProviderContext) {
@ -190,7 +190,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) {
execution_status: response.body.execution_status, execution_status: response.body.execution_status,
}); });
const esResponse = await es.get<SavedObject<RawAlert>>( const esResponse = await es.get<SavedObject<RawRule>>(
{ {
index: '.kibana', index: '.kibana',
id: `alert:${response.body.id}`, id: `alert:${response.body.id}`,

View file

@ -133,7 +133,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
savedObjects: [ savedObjects: [
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' }, { type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
], ],
message: `alert execution start: "${alertId}"`, message: `rule execution start: "${alertId}"`,
shouldHaveTask: true, shouldHaveTask: true,
rule: { rule: {
id: alertId, id: alertId,
@ -150,7 +150,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' }, { type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
], ],
outcome: 'success', outcome: 'success',
message: `alert executed: test.patternFiring:${alertId}: 'abc'`, message: `rule executed: test.patternFiring:${alertId}: 'abc'`,
status: executeStatuses[executeCount++], status: executeStatuses[executeCount++],
shouldHaveTask: true, shouldHaveTask: true,
rule: { rule: {
@ -182,15 +182,15 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
}); });
break; break;
case 'new-instance': case 'new-instance':
validateInstanceEvent(event, `created new instance: 'instance'`, false); validateInstanceEvent(event, `created new alert: 'instance'`, false);
break; break;
case 'recovered-instance': case 'recovered-instance':
validateInstanceEvent(event, `instance 'instance' has recovered`, true); validateInstanceEvent(event, `alert 'instance' has recovered`, true);
break; break;
case 'active-instance': case 'active-instance':
validateInstanceEvent( validateInstanceEvent(
event, event,
`active instance: 'instance' in actionGroup: 'default'`, `active alert: 'instance' in actionGroup: 'default'`,
false false
); );
break; break;
@ -344,7 +344,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
savedObjects: [ savedObjects: [
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' }, { type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
], ],
message: `alert execution start: "${alertId}"`, message: `rule execution start: "${alertId}"`,
shouldHaveTask: true, shouldHaveTask: true,
rule: { rule: {
id: alertId, id: alertId,
@ -361,7 +361,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' }, { type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
], ],
outcome: 'success', outcome: 'success',
message: `alert executed: test.patternFiring:${alertId}: 'abc'`, message: `rule executed: test.patternFiring:${alertId}: 'abc'`,
status: executeStatuses[executeCount++], status: executeStatuses[executeCount++],
shouldHaveTask: true, shouldHaveTask: true,
rule: { rule: {
@ -398,10 +398,10 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
}); });
break; break;
case 'new-instance': case 'new-instance':
validateInstanceEvent(event, `created new instance: 'instance'`, false); validateInstanceEvent(event, `created new alert: 'instance'`, false);
break; break;
case 'recovered-instance': case 'recovered-instance':
validateInstanceEvent(event, `instance 'instance' has recovered`, true); validateInstanceEvent(event, `alert 'instance' has recovered`, true);
break; break;
case 'active-instance': case 'active-instance':
expect( expect(
@ -411,7 +411,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
).to.be(true); ).to.be(true);
validateInstanceEvent( validateInstanceEvent(
event, event,
`active instance: 'instance' in actionGroup(subgroup): 'default(${event?.kibana?.alerting?.action_subgroup})'`, `active alert: 'instance' in actionGroup(subgroup): 'default(${event?.kibana?.alerting?.action_subgroup})'`,
false false
); );
break; break;
@ -490,7 +490,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
savedObjects: [ savedObjects: [
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' }, { type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
], ],
message: `alert execution start: "${alertId}"`, message: `rule execution start: "${alertId}"`,
shouldHaveTask: true, shouldHaveTask: true,
rule: { rule: {
id: alertId, id: alertId,
@ -504,7 +504,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
spaceId: space.id, spaceId: space.id,
savedObjects: [{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.throw' }], savedObjects: [{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.throw' }],
outcome: 'failure', outcome: 'failure',
message: `alert execution failure: test.throw:${alertId}: 'abc'`, message: `rule execution failure: test.throw:${alertId}: 'abc'`,
errorMessage: 'this alert is intended to fail', errorMessage: 'this alert is intended to fail',
status: 'error', status: 'error',
reason: 'execute', reason: 'execute',

View file

@ -9,7 +9,7 @@ import expect from '@kbn/expect';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { getUrlPrefix } from '../../../common/lib'; import { getUrlPrefix } from '../../../common/lib';
import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { FtrProviderContext } from '../../../common/ftr_provider_context';
import type { RawAlert, RawAlertAction } from '../../../../../plugins/alerting/server/types'; import type { RawRule, RawAlertAction } from '../../../../../plugins/alerting/server/types';
import { FILEBEAT_7X_INDICATOR_PATH } from '../../../../../plugins/alerting/server/saved_objects/migrations'; import { FILEBEAT_7X_INDICATOR_PATH } from '../../../../../plugins/alerting/server/saved_objects/migrations';
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@ -205,7 +205,7 @@ export default function createGetTests({ getService }: FtrProviderContext) {
}); });
it('7.16.0 migrates existing alerts to contain legacyId field', async () => { it('7.16.0 migrates existing alerts to contain legacyId field', async () => {
const searchResult = await es.search<RawAlert>( const searchResult = await es.search<RawRule>(
{ {
index: '.kibana', index: '.kibana',
body: { body: {
@ -221,13 +221,13 @@ export default function createGetTests({ getService }: FtrProviderContext) {
expect(searchResult.statusCode).to.equal(200); expect(searchResult.statusCode).to.equal(200);
expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1); expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1);
const hit = searchResult.body.hits.hits[0]; const hit = searchResult.body.hits.hits[0];
expect((hit!._source!.alert! as RawAlert).legacyId).to.equal( expect((hit!._source!.alert! as RawRule).legacyId).to.equal(
'74f3e6d7-b7bb-477d-ac28-92ee22728e6e' '74f3e6d7-b7bb-477d-ac28-92ee22728e6e'
); );
}); });
it('7.16.0 migrates existing rules so predefined connectors are not stored in references', async () => { it('7.16.0 migrates existing rules so predefined connectors are not stored in references', async () => {
const searchResult = await es.search<RawAlert>( const searchResult = await es.search<RawRule>(
{ {
index: '.kibana', index: '.kibana',
body: { body: {
@ -243,7 +243,7 @@ export default function createGetTests({ getService }: FtrProviderContext) {
expect(searchResult.statusCode).to.equal(200); expect(searchResult.statusCode).to.equal(200);
expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1); expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1);
const hit = searchResult.body.hits.hits[0]; const hit = searchResult.body.hits.hits[0];
expect((hit!._source!.alert! as RawAlert).actions! as RawAlertAction[]).to.eql([ expect((hit!._source!.alert! as RawRule).actions! as RawAlertAction[]).to.eql([
{ {
actionRef: 'action_0', actionRef: 'action_0',
actionTypeId: 'test.noop', actionTypeId: 'test.noop',
@ -348,7 +348,7 @@ export default function createGetTests({ getService }: FtrProviderContext) {
}); });
it('8.0 migrates incorrect action group spellings on the Metrics Inventory Threshold rule type', async () => { it('8.0 migrates incorrect action group spellings on the Metrics Inventory Threshold rule type', async () => {
const response = await es.get<{ alert: RawAlert }>( const response = await es.get<{ alert: RawRule }>(
{ {
index: '.kibana', index: '.kibana',
id: 'alert:92237b30-4e03-11ec-9ab9-d980518a2d28', id: 'alert:92237b30-4e03-11ec-9ab9-d980518a2d28',

View file

@ -8,7 +8,7 @@
import { Plugin, CoreSetup } from 'kibana/server'; import { Plugin, CoreSetup } from 'kibana/server';
import { import {
PluginSetupContract as AlertingSetup, PluginSetupContract as AlertingSetup,
AlertType, RuleType,
} from '../../../../../../plugins/alerting/server'; } from '../../../../../../plugins/alerting/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../plugins/features/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../plugins/features/server';
@ -18,7 +18,7 @@ export interface AlertingExampleDeps {
features: FeaturesPluginSetup; features: FeaturesPluginSetup;
} }
export const noopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = { export const noopAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
id: 'test.noop', id: 'test.noop',
name: 'Test: Noop', name: 'Test: Noop',
actionGroups: [{ id: 'default', name: 'Default' }], actionGroups: [{ id: 'default', name: 'Default' }],
@ -29,7 +29,7 @@ export const noopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
producer: 'alerts', producer: 'alerts',
}; };
export const alwaysFiringAlertType: AlertType< export const alwaysFiringAlertType: RuleType<
{ instances: Array<{ id: string; state: any }> }, { instances: Array<{ id: string; state: any }> },
never, // Only use if defining useSavedObjectReferences hook never, // Only use if defining useSavedObjectReferences hook
{ {
@ -67,7 +67,7 @@ export const alwaysFiringAlertType: AlertType<
}, },
}; };
export const failingAlertType: AlertType<never, never, never, never, never, 'default' | 'other'> = { export const failingAlertType: RuleType<never, never, never, never, never, 'default' | 'other'> = {
id: 'test.failing', id: 'test.failing',
name: 'Test: Failing', name: 'Test: Failing',
actionGroups: [ actionGroups: [