mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[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:
parent
f14540ff63
commit
7c27163d6a
82 changed files with 1163 additions and 1202 deletions
|
@ -15,7 +15,7 @@ Rules and connectors log to the Kibana logger with tags of [alerting] and [actio
|
|||
|
||||
[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.
|
||||
|
||||
|
|
|
@ -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" : {
|
||||
"message" : "Saved object [action/ef0e2530-b14a-11eb-9a7c-9df284da9f99] not found"
|
||||
},
|
||||
|
|
|
@ -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, we’d 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
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import { isEmpty } from 'lodash';
|
|||
import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
|
||||
import {
|
||||
Alert,
|
||||
AlertTaskState,
|
||||
RuleTaskState,
|
||||
LEGACY_BASE_ALERT_API_PATH,
|
||||
} from '../../../../plugins/alerting/common';
|
||||
|
||||
|
@ -34,7 +34,7 @@ type Props = RouteComponentProps & {
|
|||
};
|
||||
export const ViewAlertPage = withRouter(({ http, id }: Props) => {
|
||||
const [alert, setAlert] = useState<Alert | null>(null);
|
||||
const [alertState, setAlertState] = useState<AlertTaskState | null>(null);
|
||||
const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!alert) {
|
||||
|
@ -42,7 +42,7 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => {
|
|||
}
|
||||
if (!alertState) {
|
||||
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);
|
||||
}
|
||||
}, [alert, alertState, http, id]);
|
||||
|
|
|
@ -26,7 +26,7 @@ import { isEmpty } from 'lodash';
|
|||
import { ALERTING_EXAMPLE_APP_ID, AlwaysFiringParams } from '../../common/constants';
|
||||
import {
|
||||
Alert,
|
||||
AlertTaskState,
|
||||
RuleTaskState,
|
||||
LEGACY_BASE_ALERT_API_PATH,
|
||||
} from '../../../../plugins/alerting/common';
|
||||
|
||||
|
@ -40,7 +40,7 @@ function hasCraft(state: any): state is { craft: string } {
|
|||
}
|
||||
export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
|
||||
const [alert, setAlert] = useState<Alert<AlwaysFiringParams> | null>(null);
|
||||
const [alertState, setAlertState] = useState<AlertTaskState | null>(null);
|
||||
const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!alert) {
|
||||
|
@ -50,7 +50,7 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
|
|||
}
|
||||
if (!alertState) {
|
||||
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);
|
||||
}
|
||||
}, [alert, alertState, http, id]);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import uuid from 'uuid';
|
||||
import { range } from 'lodash';
|
||||
import { AlertType } from '../../../../plugins/alerting/server';
|
||||
import { RuleType } from '../../../../plugins/alerting/server';
|
||||
import {
|
||||
DEFAULT_INSTANCES_TO_GENERATE,
|
||||
ALERTING_EXAMPLE_APP_ID,
|
||||
|
@ -37,7 +37,7 @@ function getTShirtSizeByIdAndThreshold(
|
|||
return DEFAULT_ACTION_GROUP;
|
||||
}
|
||||
|
||||
export const alertType: AlertType<
|
||||
export const alertType: RuleType<
|
||||
AlwaysFiringParams,
|
||||
never,
|
||||
{ count?: number },
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
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';
|
||||
|
||||
interface PeopleInSpace {
|
||||
|
@ -39,7 +39,7 @@ function getCraftFilter(craft: string) {
|
|||
craft === Craft.OuterSpace ? true : craft === person.craft;
|
||||
}
|
||||
|
||||
export const alertType: AlertType<
|
||||
export const alertType: RuleType<
|
||||
{ outerSpaceCapacity: number; craft: string; op: string },
|
||||
never,
|
||||
{ peopleInSpace: number },
|
||||
|
|
|
@ -230,7 +230,7 @@ interface MyRuleTypeAlertContext extends AlertInstanceContext {
|
|||
|
||||
type MyRuleTypeActionGroups = 'default' | 'warning';
|
||||
|
||||
const myRuleType: AlertType<
|
||||
const myRuleType: RuleType<
|
||||
MyRuleTypeParams,
|
||||
MyRuleTypeExtractedParams,
|
||||
MyRuleTypeState,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ActionGroup } from './alert_type';
|
||||
import { ActionGroup } from './rule_type';
|
||||
|
||||
export type DefaultActionGroupId = 'default';
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
import { AlertsHealth } from './alert';
|
||||
|
||||
export * from './alert';
|
||||
export * from './alert_type';
|
||||
export * from './rule_type';
|
||||
export * from './alert_instance';
|
||||
export * from './alert_task_instance';
|
||||
export * from './rule_task_instance';
|
||||
export * from './alert_navigation';
|
||||
export * from './alert_summary';
|
||||
export * from './builtin_action_groups';
|
||||
|
|
|
@ -9,15 +9,15 @@ import * as t from 'io-ts';
|
|||
import { rawAlertInstance } from './alert_instance';
|
||||
import { DateFromString } from './date_from_string';
|
||||
|
||||
export const alertStateSchema = t.partial({
|
||||
export const ruleStateSchema = t.partial({
|
||||
alertTypeState: t.record(t.string, t.unknown),
|
||||
alertInstances: t.record(t.string, rawAlertInstance),
|
||||
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({
|
||||
alertId: t.string,
|
||||
}),
|
||||
|
@ -25,4 +25,4 @@ export const alertParamsSchema = t.intersection([
|
|||
spaceId: t.string,
|
||||
}),
|
||||
]);
|
||||
export type AlertTaskParams = t.TypeOf<typeof alertParamsSchema>;
|
||||
export type RuleTaskParams = t.TypeOf<typeof ruleParamsSchema>;
|
|
@ -8,7 +8,7 @@
|
|||
import { LicenseType } from '../../licensing/common/types';
|
||||
import { RecoveredActionGroupId, DefaultActionGroupId } from './builtin_action_groups';
|
||||
|
||||
export interface AlertType<
|
||||
export interface RuleType<
|
||||
ActionGroupIds extends Exclude<string, RecoveredActionGroupId> = DefaultActionGroupId,
|
||||
RecoveryActionGroupId extends string = RecoveredActionGroupId
|
||||
> {
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AlertType, RecoveredActionGroup } from '../common';
|
||||
import { RuleType, RecoveredActionGroup } from '../common';
|
||||
import { httpServiceMock } from '../../../../src/core/public/mocks';
|
||||
import { loadAlert, loadAlertType, loadAlertTypes } from './alert_api';
|
||||
import uuid from 'uuid';
|
||||
|
@ -16,7 +16,7 @@ beforeEach(() => jest.resetAllMocks());
|
|||
|
||||
describe('loadAlertTypes', () => {
|
||||
test('should call get alert types API', async () => {
|
||||
const resolvedValue: AlertType[] = [
|
||||
const resolvedValue: RuleType[] = [
|
||||
{
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
|
@ -43,7 +43,7 @@ describe('loadAlertTypes', () => {
|
|||
|
||||
describe('loadAlertType', () => {
|
||||
test('should call get alert types API', async () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: RuleType = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionVariables: ['var1'],
|
||||
|
@ -66,7 +66,7 @@ describe('loadAlertType', () => {
|
|||
});
|
||||
|
||||
test('should find the required alertType', async () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: RuleType = {
|
||||
id: 'test-another',
|
||||
name: 'Test Another',
|
||||
actionVariables: [],
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
import { HttpSetup } from 'kibana/public';
|
||||
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`);
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,11 @@ export async function loadAlertType({
|
|||
id,
|
||||
}: {
|
||||
http: HttpSetup;
|
||||
id: AlertType['id'];
|
||||
}): Promise<AlertType | undefined> {
|
||||
id: RuleType['id'];
|
||||
}): Promise<RuleType | undefined> {
|
||||
const alertTypes = (await http.get(
|
||||
`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`
|
||||
)) as AlertType[];
|
||||
)) as RuleType[];
|
||||
return alertTypes.find((type) => type.id === id);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
*/
|
||||
|
||||
import { AlertNavigationRegistry } from './alert_navigation_registry';
|
||||
import { AlertType, RecoveredActionGroup, SanitizedAlert } from '../../common';
|
||||
import { RuleType, RecoveredActionGroup, SanitizedAlert } from '../../common';
|
||||
import uuid from 'uuid';
|
||||
|
||||
beforeEach(() => jest.resetAllMocks());
|
||||
|
||||
const mockAlertType = (id: string): AlertType => ({
|
||||
const mockAlertType = (id: string): RuleType => ({
|
||||
id,
|
||||
name: id,
|
||||
actionGroups: [],
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AlertType } from '../../common';
|
||||
import { RuleType } from '../../common';
|
||||
import { AlertNavigationHandler } from './types';
|
||||
|
||||
const DEFAULT_HANDLER = Symbol('*');
|
||||
|
@ -14,7 +14,7 @@ export class AlertNavigationRegistry {
|
|||
private readonly alertNavigations: Map<string, Map<string | symbol, AlertNavigationHandler>> =
|
||||
new Map();
|
||||
|
||||
public has(consumer: string, alertType: AlertType) {
|
||||
public has(consumer: string, alertType: RuleType) {
|
||||
return this.hasTypedHandler(consumer, alertType.id) || this.hasDefaultHandler(consumer);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ export class AlertNavigationRegistry {
|
|||
consumerNavigations.set(ruleTypeId, handler);
|
||||
}
|
||||
|
||||
public get(consumer: string, alertType: AlertType): AlertNavigationHandler {
|
||||
public get(consumer: string, alertType: RuleType): AlertNavigationHandler {
|
||||
if (this.has(consumer, alertType)) {
|
||||
const consumerHandlers = this.alertNavigations.get(consumer)!;
|
||||
return (consumerHandlers.get(alertType.id) ?? consumerHandlers.get(DEFAULT_HANDLER))!;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
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 (
|
||||
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}`,
|
||||
fields: ['executionStatus'],
|
||||
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}`,
|
||||
fields: ['executionStatus'],
|
||||
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}`,
|
||||
fields: ['executionStatus'],
|
||||
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',
|
||||
fields: ['executionStatus'],
|
||||
type: 'alert',
|
||||
|
|
|
@ -14,7 +14,7 @@ import { AlertsConfigType } from './types';
|
|||
export type RulesClient = PublicMethodsOf<RulesClientClass>;
|
||||
|
||||
export type {
|
||||
AlertType,
|
||||
RuleType,
|
||||
ActionGroup,
|
||||
ActionGroupIdsOf,
|
||||
AlertingPlugin,
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
*/
|
||||
|
||||
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';
|
||||
|
||||
describe('createAlertEventLogRecordObject', () => {
|
||||
const ruleType: jest.Mocked<UntypedNormalizedAlertType> = {
|
||||
const ruleType: jest.Mocked<UntypedNormalizedRuleType> = {
|
||||
id: 'test',
|
||||
name: 'My test alert',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup],
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
import { AlertInstanceState } from '../types';
|
||||
import { IEvent } from '../../../event_log/server';
|
||||
import { UntypedNormalizedAlertType } from '../rule_type_registry';
|
||||
import { UntypedNormalizedRuleType } from '../rule_type_registry';
|
||||
|
||||
export type Event = Exclude<IEvent, undefined>;
|
||||
|
||||
interface CreateAlertEventLogRecordParams {
|
||||
ruleId: string;
|
||||
ruleType: UntypedNormalizedAlertType;
|
||||
ruleType: UntypedNormalizedRuleType;
|
||||
action: string;
|
||||
ruleName?: string;
|
||||
instanceId?: string;
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export function getAlertTypeFeatureUsageName(alertTypeName: string) {
|
||||
return `Alert: ${alertTypeName}`;
|
||||
export function getRuleTypeFeatureUsageName(ruleTypeName: string) {
|
||||
return `Rule: ${ruleTypeName}`;
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
export { parseDuration, validateDurationSchema } from '../../common/parse_duration';
|
||||
export type { ILicenseState } 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 { verifyApiAccess } from './license_api_access';
|
||||
export { ErrorWithReason, getReasonFromError, isErrorWithReason } from './error_with_reason';
|
||||
|
@ -21,6 +21,6 @@ export { AlertTypeDisabledError, isErrorThatHandlesItsOwnResponse } from './erro
|
|||
export {
|
||||
executionStatusFromState,
|
||||
executionStatusFromError,
|
||||
alertExecutionStatusToRaw,
|
||||
alertExecutionStatusFromRaw,
|
||||
} from './alert_execution_status';
|
||||
ruleExecutionStatusToRaw,
|
||||
ruleExecutionStatusFromRaw,
|
||||
} from './rule_execution_status';
|
||||
|
|
|
@ -11,8 +11,8 @@ export const createLicenseStateMock = () => {
|
|||
const licenseState: jest.Mocked<ILicenseState> = {
|
||||
clean: jest.fn(),
|
||||
getLicenseInformation: jest.fn(),
|
||||
ensureLicenseForAlertType: jest.fn(),
|
||||
getLicenseCheckForAlertType: jest.fn().mockResolvedValue({
|
||||
ensureLicenseForRuleType: jest.fn(),
|
||||
getLicenseCheckForRuleType: jest.fn().mockResolvedValue({
|
||||
isValid: true,
|
||||
}),
|
||||
checkLicense: jest.fn().mockResolvedValue({
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AlertType } from '../types';
|
||||
import { RuleType } from '../types';
|
||||
import { Subject } from 'rxjs';
|
||||
import { LicenseState, ILicenseState } from './license_state';
|
||||
import { licensingMock } from '../../../licensing/server/mocks';
|
||||
|
@ -53,11 +53,11 @@ describe('checkLicense()', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getLicenseCheckForAlertType', () => {
|
||||
describe('getLicenseCheckForRuleType', () => {
|
||||
let license: Subject<ILicense>;
|
||||
let licenseState: ILicenseState;
|
||||
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',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -82,10 +82,10 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
|
||||
test('should return false when license not defined', () => {
|
||||
expect(
|
||||
licenseState.getLicenseCheckForAlertType(
|
||||
alertType.id,
|
||||
alertType.name,
|
||||
alertType.minimumLicenseRequired
|
||||
licenseState.getLicenseCheckForRuleType(
|
||||
ruleType.id,
|
||||
ruleType.name,
|
||||
ruleType.minimumLicenseRequired
|
||||
)
|
||||
).toEqual({
|
||||
isValid: false,
|
||||
|
@ -96,10 +96,10 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
test('should return false when license not available', () => {
|
||||
license.next(createUnavailableLicense());
|
||||
expect(
|
||||
licenseState.getLicenseCheckForAlertType(
|
||||
alertType.id,
|
||||
alertType.name,
|
||||
alertType.minimumLicenseRequired
|
||||
licenseState.getLicenseCheckForRuleType(
|
||||
ruleType.id,
|
||||
ruleType.name,
|
||||
ruleType.minimumLicenseRequired
|
||||
)
|
||||
).toEqual({
|
||||
isValid: false,
|
||||
|
@ -111,10 +111,10 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
const expiredLicense = licensingMock.createLicense({ license: { status: 'expired' } });
|
||||
license.next(expiredLicense);
|
||||
expect(
|
||||
licenseState.getLicenseCheckForAlertType(
|
||||
alertType.id,
|
||||
alertType.name,
|
||||
alertType.minimumLicenseRequired
|
||||
licenseState.getLicenseCheckForRuleType(
|
||||
ruleType.id,
|
||||
ruleType.name,
|
||||
ruleType.minimumLicenseRequired
|
||||
)
|
||||
).toEqual({
|
||||
isValid: false,
|
||||
|
@ -128,10 +128,10 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
});
|
||||
license.next(basicLicense);
|
||||
expect(
|
||||
licenseState.getLicenseCheckForAlertType(
|
||||
alertType.id,
|
||||
alertType.name,
|
||||
alertType.minimumLicenseRequired
|
||||
licenseState.getLicenseCheckForRuleType(
|
||||
ruleType.id,
|
||||
ruleType.name,
|
||||
ruleType.minimumLicenseRequired
|
||||
)
|
||||
).toEqual({
|
||||
isValid: false,
|
||||
|
@ -145,10 +145,10 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
});
|
||||
license.next(goldLicense);
|
||||
expect(
|
||||
licenseState.getLicenseCheckForAlertType(
|
||||
alertType.id,
|
||||
alertType.name,
|
||||
alertType.minimumLicenseRequired
|
||||
licenseState.getLicenseCheckForRuleType(
|
||||
ruleType.id,
|
||||
ruleType.name,
|
||||
ruleType.minimumLicenseRequired
|
||||
)
|
||||
).toEqual({
|
||||
isValid: true,
|
||||
|
@ -160,7 +160,7 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
license: { status: 'active', type: 'gold' },
|
||||
});
|
||||
license.next(goldLicense);
|
||||
licenseState.getLicenseCheckForAlertType(alertType.id, alertType.name, 'gold');
|
||||
licenseState.getLicenseCheckForRuleType(ruleType.id, ruleType.name, 'gold');
|
||||
expect(mockNotifyUsage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -169,7 +169,7 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
license: { status: 'active', type: 'basic' },
|
||||
});
|
||||
license.next(basicLicense);
|
||||
licenseState.getLicenseCheckForAlertType(alertType.id, alertType.name, 'basic');
|
||||
licenseState.getLicenseCheckForRuleType(ruleType.id, ruleType.name, 'basic');
|
||||
expect(mockNotifyUsage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -178,21 +178,21 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
license: { status: 'active', type: 'gold' },
|
||||
});
|
||||
license.next(goldLicense);
|
||||
licenseState.getLicenseCheckForAlertType(
|
||||
alertType.id,
|
||||
alertType.name,
|
||||
alertType.minimumLicenseRequired,
|
||||
licenseState.getLicenseCheckForRuleType(
|
||||
ruleType.id,
|
||||
ruleType.name,
|
||||
ruleType.minimumLicenseRequired,
|
||||
{ notifyUsage: true }
|
||||
);
|
||||
expect(mockNotifyUsage).toHaveBeenCalledWith('Alert: Test');
|
||||
expect(mockNotifyUsage).toHaveBeenCalledWith('Rule: Test');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ensureLicenseForAlertType()', () => {
|
||||
describe('ensureLicenseForRuleType()', () => {
|
||||
let license: Subject<ILicense>;
|
||||
let licenseState: ILicenseState;
|
||||
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',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -217,18 +217,18 @@ describe('ensureLicenseForAlertType()', () => {
|
|||
|
||||
test('should throw when license not defined', () => {
|
||||
expect(() =>
|
||||
licenseState.ensureLicenseForAlertType(alertType)
|
||||
licenseState.ensureLicenseForRuleType(ruleType)
|
||||
).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', () => {
|
||||
license.next(createUnavailableLicense());
|
||||
expect(() =>
|
||||
licenseState.ensureLicenseForAlertType(alertType)
|
||||
licenseState.ensureLicenseForRuleType(ruleType)
|
||||
).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' } });
|
||||
license.next(expiredLicense);
|
||||
expect(() =>
|
||||
licenseState.ensureLicenseForAlertType(alertType)
|
||||
licenseState.ensureLicenseForRuleType(ruleType)
|
||||
).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);
|
||||
expect(() =>
|
||||
licenseState.ensureLicenseForAlertType(alertType)
|
||||
licenseState.ensureLicenseForRuleType(ruleType)
|
||||
).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.next(goldLicense);
|
||||
licenseState.ensureLicenseForAlertType(alertType);
|
||||
licenseState.ensureLicenseForRuleType(ruleType);
|
||||
});
|
||||
|
||||
test('should call notifyUsage', () => {
|
||||
|
@ -267,8 +267,8 @@ describe('ensureLicenseForAlertType()', () => {
|
|||
license: { status: 'active', type: 'gold' },
|
||||
});
|
||||
license.next(goldLicense);
|
||||
licenseState.ensureLicenseForAlertType(alertType);
|
||||
expect(mockNotifyUsage).toHaveBeenCalledWith('Alert: Test');
|
||||
licenseState.ensureLicenseForRuleType(ruleType);
|
||||
expect(mockNotifyUsage).toHaveBeenCalledWith('Rule: Test');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ import { Observable, Subscription } from 'rxjs';
|
|||
import { LicensingPluginStart } from '../../../licensing/server';
|
||||
import { ILicense, LicenseType } from '../../../licensing/common/types';
|
||||
import { PLUGIN } from '../constants/plugin';
|
||||
import { getAlertTypeFeatureUsageName } from './get_alert_type_feature_usage_name';
|
||||
import { getRuleTypeFeatureUsageName } from './get_rule_type_feature_usage_name';
|
||||
import {
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
|
@ -68,21 +68,21 @@ export class LicenseState {
|
|||
this._notifyUsage = notifyUsage;
|
||||
}
|
||||
|
||||
public getLicenseCheckForAlertType(
|
||||
alertTypeId: string,
|
||||
alertTypeName: string,
|
||||
public getLicenseCheckForRuleType(
|
||||
ruleTypeId: string,
|
||||
ruleTypeName: string,
|
||||
minimumLicenseRequired: LicenseType,
|
||||
{ notifyUsage }: { notifyUsage: boolean } = { notifyUsage: false }
|
||||
): { isValid: true } | { isValid: false; reason: 'unavailable' | 'expired' | 'invalid' } {
|
||||
if (notifyUsage) {
|
||||
this.notifyUsage(alertTypeName, minimumLicenseRequired);
|
||||
this.notifyUsage(ruleTypeName, minimumLicenseRequired);
|
||||
}
|
||||
|
||||
if (!this.license?.isAvailable) {
|
||||
return { isValid: false, reason: 'unavailable' };
|
||||
}
|
||||
|
||||
const check = this.license.check(alertTypeId, minimumLicenseRequired);
|
||||
const check = this.license.check(ruleTypeId, minimumLicenseRequired);
|
||||
|
||||
switch (check.state) {
|
||||
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
|
||||
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,
|
||||
ExtractedParams extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
|
@ -156,7 +156,7 @@ export class LicenseState {
|
|||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: AlertType<
|
||||
ruleType: RuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -166,12 +166,12 @@ export class LicenseState {
|
|||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
this.notifyUsage(alertType.name, alertType.minimumLicenseRequired);
|
||||
this.notifyUsage(ruleType.name, ruleType.minimumLicenseRequired);
|
||||
|
||||
const check = this.getLicenseCheckForAlertType(
|
||||
alertType.id,
|
||||
alertType.name,
|
||||
alertType.minimumLicenseRequired
|
||||
const check = this.getLicenseCheckForRuleType(
|
||||
ruleType.id,
|
||||
ruleType.name,
|
||||
ruleType.minimumLicenseRequired
|
||||
);
|
||||
|
||||
if (check.isValid) {
|
||||
|
@ -182,9 +182,9 @@ export class LicenseState {
|
|||
throw new AlertTypeDisabledError(
|
||||
i18n.translate('xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage', {
|
||||
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: {
|
||||
alertTypeId: alertType.id,
|
||||
ruleTypeId: ruleType.id,
|
||||
},
|
||||
}),
|
||||
'license_unavailable'
|
||||
|
@ -193,8 +193,8 @@ export class LicenseState {
|
|||
throw new AlertTypeDisabledError(
|
||||
i18n.translate('xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage', {
|
||||
defaultMessage:
|
||||
'Alert type {alertTypeId} is disabled because your {licenseType} license has expired.',
|
||||
values: { alertTypeId: alertType.id, licenseType: this.license!.type },
|
||||
'Rule type {ruleTypeId} is disabled because your {licenseType} license has expired.',
|
||||
values: { ruleTypeId: ruleType.id, licenseType: this.license!.type },
|
||||
}),
|
||||
'license_expired'
|
||||
);
|
||||
|
@ -202,10 +202,10 @@ export class LicenseState {
|
|||
throw new AlertTypeDisabledError(
|
||||
i18n.translate('xpack.alerting.serverSideErrors.invalidLicenseErrorMessage', {
|
||||
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: {
|
||||
alertTypeId: alertType.id,
|
||||
licenseType: capitalize(alertType.minimumLicenseRequired),
|
||||
ruleTypeId: ruleType.id,
|
||||
licenseType: capitalize(ruleType.minimumLicenseRequired),
|
||||
},
|
||||
}),
|
||||
'license_invalid'
|
||||
|
|
|
@ -10,14 +10,14 @@ import { AlertExecutionStatusErrorReasons } from '../types';
|
|||
import {
|
||||
executionStatusFromState,
|
||||
executionStatusFromError,
|
||||
alertExecutionStatusToRaw,
|
||||
alertExecutionStatusFromRaw,
|
||||
} from './alert_execution_status';
|
||||
ruleExecutionStatusToRaw,
|
||||
ruleExecutionStatusFromRaw,
|
||||
} from './rule_execution_status';
|
||||
import { ErrorWithReason } from './error_with_reason';
|
||||
|
||||
const MockLogger = loggingSystemMock.create().get();
|
||||
|
||||
describe('AlertExecutionStatus', () => {
|
||||
describe('RuleExecutionStatus', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
@ -71,14 +71,14 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('alertExecutionStatusToRaw()', () => {
|
||||
describe('ruleExecutionStatusToRaw()', () => {
|
||||
const date = new Date('2020-09-03T16:26:58Z');
|
||||
const status = 'ok';
|
||||
const reason = AlertExecutionStatusErrorReasons.Decrypt;
|
||||
const error = { reason, message: 'wops' };
|
||||
|
||||
test('status without an error', () => {
|
||||
expect(alertExecutionStatusToRaw({ lastExecutionDate: date, status })).toMatchInlineSnapshot(`
|
||||
expect(ruleExecutionStatusToRaw({ lastExecutionDate: date, status })).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"error": null,
|
||||
"lastDuration": 0,
|
||||
|
@ -89,7 +89,7 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
|
||||
test('status with an error', () => {
|
||||
expect(alertExecutionStatusToRaw({ lastExecutionDate: date, status, error }))
|
||||
expect(ruleExecutionStatusToRaw({ lastExecutionDate: date, status, error }))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"error": Object {
|
||||
|
@ -104,7 +104,7 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
|
||||
test('status with a duration', () => {
|
||||
expect(alertExecutionStatusToRaw({ lastExecutionDate: date, status, lastDuration: 1234 }))
|
||||
expect(ruleExecutionStatusToRaw({ lastExecutionDate: date, status, lastDuration: 1234 }))
|
||||
.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"error": null,
|
||||
|
@ -116,41 +116,41 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('alertExecutionStatusFromRaw()', () => {
|
||||
describe('ruleExecutionStatusFromRaw()', () => {
|
||||
const date = new Date('2020-09-03T16:26:58Z').toISOString();
|
||||
const status = 'active';
|
||||
const reason = AlertExecutionStatusErrorReasons.Execute;
|
||||
const error = { reason, message: 'wops' };
|
||||
|
||||
test('no input', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id');
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id');
|
||||
expect(result).toBe(undefined);
|
||||
});
|
||||
|
||||
test('undefined input', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', undefined);
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', undefined);
|
||||
expect(result).toBe(undefined);
|
||||
});
|
||||
|
||||
test('null input', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', null);
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', null);
|
||||
expect(result).toBe(undefined);
|
||||
});
|
||||
|
||||
test('invalid date', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', {
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
|
||||
lastExecutionDate: 'an invalid date',
|
||||
})!;
|
||||
checkDateIsNearNow(result.lastExecutionDate);
|
||||
expect(result.status).toBe('unknown');
|
||||
expect(result.error).toBe(undefined);
|
||||
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', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', {
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
|
||||
lastExecutionDate: date,
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
|
@ -162,7 +162,7 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
|
||||
test('valid status and date', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', {
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
|
||||
status,
|
||||
lastExecutionDate: date,
|
||||
});
|
||||
|
@ -175,7 +175,7 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
|
||||
test('valid status, date and error', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', {
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
|
||||
status,
|
||||
lastExecutionDate: date,
|
||||
error,
|
||||
|
@ -193,7 +193,7 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
|
||||
test('valid status, date and duration', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', {
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
|
||||
status,
|
||||
lastExecutionDate: date,
|
||||
lastDuration: 1234,
|
||||
|
@ -208,7 +208,7 @@ describe('AlertExecutionStatus', () => {
|
|||
});
|
||||
|
||||
test('valid status, date, error and duration', () => {
|
||||
const result = alertExecutionStatusFromRaw(MockLogger, 'alert-id', {
|
||||
const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', {
|
||||
status,
|
||||
lastExecutionDate: date,
|
||||
error,
|
|
@ -6,16 +6,16 @@
|
|||
*/
|
||||
|
||||
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 { getEsErrorMessage } from './errors';
|
||||
import { AlertExecutionStatuses } from '../../common';
|
||||
|
||||
export function executionStatusFromState(state: AlertTaskState): AlertExecutionStatus {
|
||||
const instanceIds = Object.keys(state.alertInstances ?? {});
|
||||
export function executionStatusFromState(state: RuleTaskState): AlertExecutionStatus {
|
||||
const alertIds = Object.keys(state.alertInstances ?? {});
|
||||
return {
|
||||
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,
|
||||
lastDuration,
|
||||
status,
|
||||
error,
|
||||
}: AlertExecutionStatus): RawAlertExecutionStatus {
|
||||
}: AlertExecutionStatus): RawRuleExecutionStatus {
|
||||
return {
|
||||
lastExecutionDate: lastExecutionDate.toISOString(),
|
||||
lastDuration: lastDuration ?? 0,
|
||||
|
@ -45,19 +45,19 @@ export function alertExecutionStatusToRaw({
|
|||
};
|
||||
}
|
||||
|
||||
export function alertExecutionStatusFromRaw(
|
||||
export function ruleExecutionStatusFromRaw(
|
||||
logger: Logger,
|
||||
alertId: string,
|
||||
rawAlertExecutionStatus?: Partial<RawAlertExecutionStatus> | null | undefined
|
||||
ruleId: string,
|
||||
rawRuleExecutionStatus?: Partial<RawRuleExecutionStatus> | null | 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();
|
||||
if (isNaN(parsedDateMillis)) {
|
||||
logger.debug(
|
||||
`invalid alertExecutionStatus lastExecutionDate "${lastExecutionDate}" in raw alert ${alertId}`
|
||||
`invalid ruleExecutionStatus lastExecutionDate "${lastExecutionDate}" in raw rule ${ruleId}`
|
||||
);
|
||||
parsedDateMillis = Date.now();
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ export function alertExecutionStatusFromRaw(
|
|||
return executionStatus;
|
||||
}
|
||||
|
||||
export const getAlertExecutionStatusPending = (lastExecutionDate: string) => ({
|
||||
export const getRuleExecutionStatusPending = (lastExecutionDate: string) => ({
|
||||
status: 'pending' as AlertExecutionStatuses,
|
||||
lastExecutionDate,
|
||||
error: null,
|
|
@ -6,17 +6,17 @@
|
|||
*/
|
||||
|
||||
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', () => {
|
||||
const result = validateAlertTypeParams({
|
||||
const result = validateRuleTypeParams({
|
||||
foo: true,
|
||||
});
|
||||
expect(result).toEqual({ foo: true });
|
||||
});
|
||||
|
||||
test('should validate and apply defaults when params is valid', () => {
|
||||
const result = validateAlertTypeParams(
|
||||
const result = validateRuleTypeParams(
|
||||
{ param1: 'value' },
|
||||
schema.object({
|
||||
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', () => {
|
||||
expect(() =>
|
||||
validateAlertTypeParams(
|
||||
validateRuleTypeParams(
|
||||
{},
|
||||
schema.object({
|
||||
param1: schema.string(),
|
|
@ -8,7 +8,7 @@
|
|||
import Boom from '@hapi/boom';
|
||||
import { AlertTypeParams, AlertTypeParamsValidator } from '../types';
|
||||
|
||||
export function validateAlertTypeParams<Params extends AlertTypeParams>(
|
||||
export function validateRuleTypeParams<Params extends AlertTypeParams>(
|
||||
params: Record<string, unknown>,
|
||||
validator?: AlertTypeParamsValidator<Params>
|
||||
): Params {
|
|
@ -16,7 +16,7 @@ import { KibanaRequest } from 'kibana/server';
|
|||
import { featuresPluginMock } from '../../features/server/mocks';
|
||||
import { KibanaFeature } from '../../features/server';
|
||||
import { AlertsConfig } from './config';
|
||||
import { AlertType } from './types';
|
||||
import { RuleType } from './types';
|
||||
import { eventLogMock } from '../../event_log/server/mocks';
|
||||
import { actionsMock } from '../../actions/server/mocks';
|
||||
|
||||
|
@ -99,7 +99,7 @@ describe('Alerting Plugin', () => {
|
|||
|
||||
describe('registerType()', () => {
|
||||
let setup: PluginSetupContract;
|
||||
const sampleAlertType: AlertType<never, never, never, never, never, 'default'> = {
|
||||
const sampleRuleType: RuleType<never, never, never, never, never, 'default'> = {
|
||||
id: 'test',
|
||||
name: 'test',
|
||||
minimumLicenseRequired: 'basic',
|
||||
|
@ -126,7 +126,7 @@ describe('Alerting Plugin', () => {
|
|||
it('should throw error when license type is invalid', async () => {
|
||||
expect(() =>
|
||||
setup.registerType({
|
||||
...sampleAlertType,
|
||||
...sampleRuleType,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
minimumLicenseRequired: 'foo' as any,
|
||||
})
|
||||
|
@ -135,52 +135,52 @@ describe('Alerting Plugin', () => {
|
|||
|
||||
it('should not throw when license type is gold', async () => {
|
||||
setup.registerType({
|
||||
...sampleAlertType,
|
||||
...sampleRuleType,
|
||||
minimumLicenseRequired: 'gold',
|
||||
});
|
||||
});
|
||||
|
||||
it('should not throw when license type is basic', async () => {
|
||||
setup.registerType({
|
||||
...sampleAlertType,
|
||||
...sampleRuleType,
|
||||
minimumLicenseRequired: 'basic',
|
||||
});
|
||||
});
|
||||
|
||||
it('should apply default config value for ruleTaskTimeout if no value is specified', async () => {
|
||||
const ruleType = {
|
||||
...sampleAlertType,
|
||||
...sampleRuleType,
|
||||
minimumLicenseRequired: 'basic',
|
||||
} as AlertType<never, never, never, never, never, 'default', never>;
|
||||
} as RuleType<never, never, never, never, never, 'default', never>;
|
||||
await setup.registerType(ruleType);
|
||||
expect(ruleType.ruleTaskTimeout).toBe('5m');
|
||||
});
|
||||
|
||||
it('should apply value for ruleTaskTimeout if specified', async () => {
|
||||
const ruleType = {
|
||||
...sampleAlertType,
|
||||
...sampleRuleType,
|
||||
minimumLicenseRequired: 'basic',
|
||||
ruleTaskTimeout: '20h',
|
||||
} as AlertType<never, never, never, never, never, 'default', never>;
|
||||
} as RuleType<never, never, never, never, never, 'default', never>;
|
||||
await setup.registerType(ruleType);
|
||||
expect(ruleType.ruleTaskTimeout).toBe('20h');
|
||||
});
|
||||
|
||||
it('should apply default config value for cancelAlertsOnRuleTimeout if no value is specified', async () => {
|
||||
const ruleType = {
|
||||
...sampleAlertType,
|
||||
...sampleRuleType,
|
||||
minimumLicenseRequired: 'basic',
|
||||
} as AlertType<never, never, never, never, never, 'default', never>;
|
||||
} as RuleType<never, never, never, never, never, 'default', never>;
|
||||
await setup.registerType(ruleType);
|
||||
expect(ruleType.cancelAlertsOnRuleTimeout).toBe(true);
|
||||
});
|
||||
|
||||
it('should apply value for cancelAlertsOnRuleTimeout if specified', async () => {
|
||||
const ruleType = {
|
||||
...sampleAlertType,
|
||||
...sampleRuleType,
|
||||
minimumLicenseRequired: 'basic',
|
||||
cancelAlertsOnRuleTimeout: false,
|
||||
} as AlertType<never, never, never, never, never, 'default', never>;
|
||||
} as RuleType<never, never, never, never, never, 'default', never>;
|
||||
await setup.registerType(ruleType);
|
||||
expect(ruleType.cancelAlertsOnRuleTimeout).toBe(false);
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ import {
|
|||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertsHealth,
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
Services,
|
||||
|
@ -91,7 +91,7 @@ export interface PluginSetupContract {
|
|||
ActionGroupIds extends string = never,
|
||||
RecoveryActionGroupId extends string = never
|
||||
>(
|
||||
alertType: AlertType<
|
||||
ruleType: RuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -273,7 +273,7 @@ export class AlertingPlugin {
|
|||
ActionGroupIds extends string = never,
|
||||
RecoveryActionGroupId extends string = never
|
||||
>(
|
||||
alertType: AlertType<
|
||||
ruleType: RuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -283,15 +283,15 @@ export class AlertingPlugin {
|
|||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
if (!(alertType.minimumLicenseRequired in LICENSE_TYPE)) {
|
||||
throw new Error(`"${alertType.minimumLicenseRequired}" is not a valid license type`);
|
||||
if (!(ruleType.minimumLicenseRequired in LICENSE_TYPE)) {
|
||||
throw new Error(`"${ruleType.minimumLicenseRequired}" is not a valid license type`);
|
||||
}
|
||||
|
||||
alertingConfig.then((config) => {
|
||||
alertType.ruleTaskTimeout = alertType.ruleTaskTimeout ?? config.defaultRuleTaskTimeout;
|
||||
alertType.cancelAlertsOnRuleTimeout =
|
||||
alertType.cancelAlertsOnRuleTimeout ?? config.cancelAlertsOnRuleTimeout;
|
||||
ruleTypeRegistry.register(alertType);
|
||||
ruleType.ruleTaskTimeout = ruleType.ruleTaskTimeout ?? config.defaultRuleTaskTimeout;
|
||||
ruleType.cancelAlertsOnRuleTimeout =
|
||||
ruleType.cancelAlertsOnRuleTimeout ?? config.cancelAlertsOnRuleTimeout;
|
||||
ruleTypeRegistry.register(ruleType);
|
||||
});
|
||||
},
|
||||
getSecurityHealth: async () => {
|
||||
|
@ -390,7 +390,7 @@ export class AlertingPlugin {
|
|||
ruleTypeRegistry: this.ruleTypeRegistry!,
|
||||
kibanaBaseUrl: this.kibanaBaseUrl,
|
||||
supportsEphemeralTasks: plugins.taskManager.supportsEphemeralTasks(),
|
||||
maxEphemeralActionsPerAlert: config.maxEphemeralActionsPerAlert,
|
||||
maxEphemeralActionsPerRule: config.maxEphemeralActionsPerAlert,
|
||||
cancelAlertsOnRuleTimeout: config.cancelAlertsOnRuleTimeout,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ import { identity } from 'lodash';
|
|||
import type { MethodKeysOf } from '@kbn/utility-types';
|
||||
import { httpServerMock } from '../../../../../src/core/server/mocks';
|
||||
import { rulesClientMock, RulesClientMock } from '../rules_client.mock';
|
||||
import { AlertsHealth, AlertType } from '../../common';
|
||||
import { AlertsHealth, RuleType } from '../../common';
|
||||
import type { AlertingRequestHandlerContext } from '../types';
|
||||
|
||||
export function mockHandlerArguments(
|
||||
|
@ -21,7 +21,7 @@ export function mockHandlerArguments(
|
|||
areApiKeysEnabled,
|
||||
}: {
|
||||
rulesClient?: RulesClientMock;
|
||||
listTypes?: AlertType[];
|
||||
listTypes?: RuleType[];
|
||||
getFrameworkHealth?: jest.MockInstance<Promise<AlertsHealth>, []> &
|
||||
(() => Promise<AlertsHealth>);
|
||||
areApiKeysEnabled?: () => Promise<boolean>;
|
||||
|
|
|
@ -12,14 +12,14 @@ import { RewriteResponseCase, verifyAccessAndContext } from './lib';
|
|||
import {
|
||||
AlertingRequestHandlerContext,
|
||||
INTERNAL_BASE_ALERTING_API_PATH,
|
||||
AlertTaskState,
|
||||
RuleTaskState,
|
||||
} from '../types';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
const rewriteBodyRes: RewriteResponseCase<AlertTaskState> = ({
|
||||
const rewriteBodyRes: RewriteResponseCase<RuleTaskState> = ({
|
||||
alertTypeState,
|
||||
alertInstances,
|
||||
previousStartedAt,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { TaskRunnerFactory } from './task_runner';
|
||||
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 { ILicenseState } from './lib/license_state';
|
||||
import { licenseStateMock } from './lib/license_state.mock';
|
||||
|
@ -56,8 +56,8 @@ describe('has()', () => {
|
|||
});
|
||||
|
||||
describe('register()', () => {
|
||||
test('throws if AlertType Id contains invalid characters', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default'> = {
|
||||
test('throws if RuleType Id contains invalid characters', () => {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -76,21 +76,21 @@ describe('register()', () => {
|
|||
|
||||
const invalidCharacters = [' ', ':', '*', '*', '/'];
|
||||
for (const char of invalidCharacters) {
|
||||
expect(() => registry.register({ ...alertType, id: `${alertType.id}${char}` })).toThrowError(
|
||||
new Error(`expected AlertType Id not to include invalid character: ${char}`)
|
||||
expect(() => registry.register({ ...ruleType, id: `${ruleType.id}${char}` })).toThrowError(
|
||||
new Error(`expected RuleType Id not to include invalid character: ${char}`)
|
||||
);
|
||||
}
|
||||
|
||||
const [first, second] = invalidCharacters;
|
||||
expect(() =>
|
||||
registry.register({ ...alertType, id: `${first}${alertType.id}${second}` })
|
||||
registry.register({ ...ruleType, id: `${first}${ruleType.id}${second}` })
|
||||
).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', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default'> = {
|
||||
test('throws if RuleType Id isnt a string', () => {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default'> = {
|
||||
id: 123 as unknown as string,
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -107,13 +107,13 @@ describe('register()', () => {
|
|||
};
|
||||
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]`)
|
||||
);
|
||||
});
|
||||
|
||||
test('throws if AlertType ruleTaskTimeout is not a valid duration', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default'> = {
|
||||
test('throws if RuleType ruleTaskTimeout is not a valid duration', () => {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default'> = {
|
||||
id: '123',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -131,7 +131,7 @@ describe('register()', () => {
|
|||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
|
||||
expect(() => registry.register(alertType)).toThrowError(
|
||||
expect(() => registry.register(ruleType)).toThrowError(
|
||||
new Error(
|
||||
`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', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default'> = {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default'> = {
|
||||
id: '123',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -158,7 +158,7 @@ describe('register()', () => {
|
|||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
|
||||
expect(() => registry.register(alertType)).toThrowError(
|
||||
expect(() => registry.register(ruleType)).toThrowError(
|
||||
new Error(
|
||||
`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', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default'> = {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default'> = {
|
||||
id: '123',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -184,7 +184,7 @@ describe('register()', () => {
|
|||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
|
||||
expect(() => registry.register(alertType)).toThrowError(
|
||||
expect(() => registry.register(ruleType)).toThrowError(
|
||||
new Error(
|
||||
`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', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default' | 'NotReserved'> = {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default' | 'NotReserved'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -217,15 +217,15 @@ describe('register()', () => {
|
|||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
|
||||
expect(() => registry.register(alertType)).toThrowError(
|
||||
expect(() => registry.register(ruleType)).toThrowError(
|
||||
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', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default', 'backToAwesome'> = {
|
||||
test('allows an RuleType to specify a custom recovery group', () => {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default', 'backToAwesome'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -245,7 +245,7 @@ describe('register()', () => {
|
|||
isExportable: true,
|
||||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
registry.register(alertType);
|
||||
registry.register(ruleType);
|
||||
expect(registry.get('test').actionGroups).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
|
@ -260,8 +260,8 @@ describe('register()', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('allows an AlertType to specify a custom rule task timeout', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default', 'backToAwesome'> = {
|
||||
test('allows an RuleType to specify a custom rule task timeout', () => {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default', 'backToAwesome'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -278,12 +278,12 @@ describe('register()', () => {
|
|||
isExportable: true,
|
||||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
registry.register(alertType);
|
||||
registry.register(ruleType);
|
||||
expect(registry.get('test').ruleTaskTimeout).toBe('13m');
|
||||
});
|
||||
|
||||
test('throws if the custom recovery group is contained in the AlertType action groups', () => {
|
||||
const alertType: AlertType<
|
||||
test('throws if the custom recovery group is contained in the RuleType action groups', () => {
|
||||
const ruleType: RuleType<
|
||||
never,
|
||||
never,
|
||||
never,
|
||||
|
@ -316,15 +316,15 @@ describe('register()', () => {
|
|||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
|
||||
expect(() => registry.register(alertType)).toThrowError(
|
||||
expect(() => registry.register(ruleType)).toThrowError(
|
||||
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', () => {
|
||||
const alertType: AlertType<never, never, never, never, never, 'default'> = {
|
||||
const ruleType: RuleType<never, never, never, never, never, 'default'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -341,7 +341,7 @@ describe('register()', () => {
|
|||
ruleTaskTimeout: '20m',
|
||||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
registry.register(alertType);
|
||||
registry.register(ruleType);
|
||||
expect(taskManager.registerTaskDefinitions).toHaveBeenCalledTimes(1);
|
||||
expect(taskManager.registerTaskDefinitions.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
|
@ -357,7 +357,7 @@ describe('register()', () => {
|
|||
});
|
||||
|
||||
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',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -373,8 +373,8 @@ describe('register()', () => {
|
|||
producer: 'alerts',
|
||||
};
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
registry.register(alertType);
|
||||
alertType.name = 'Changed';
|
||||
registry.register(ruleType);
|
||||
ruleType.name = 'Changed';
|
||||
expect(registry.get('test').name).toEqual('Test');
|
||||
});
|
||||
|
||||
|
@ -433,8 +433,8 @@ describe('get()', () => {
|
|||
executor: jest.fn(),
|
||||
producer: 'alerts',
|
||||
});
|
||||
const alertType = registry.get('test');
|
||||
expect(alertType).toMatchInlineSnapshot(`
|
||||
const ruleType = registry.get('test');
|
||||
expect(ruleType).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"actionGroups": Array [
|
||||
Object {
|
||||
|
@ -539,12 +539,12 @@ describe('list()', () => {
|
|||
|
||||
test('should return action variables state and empty context', () => {
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
registry.register(alertTypeWithVariables('x', '', 's'));
|
||||
const alertType = registry.get('x');
|
||||
expect(alertType.actionVariables).toBeTruthy();
|
||||
registry.register(ruleTypeWithVariables('x', '', 's'));
|
||||
const ruleType = registry.get('x');
|
||||
expect(ruleType.actionVariables).toBeTruthy();
|
||||
|
||||
const context = alertType.actionVariables!.context;
|
||||
const state = alertType.actionVariables!.state;
|
||||
const context = ruleType.actionVariables!.context;
|
||||
const state = ruleType.actionVariables!.state;
|
||||
|
||||
expect(context).toBeTruthy();
|
||||
expect(context!.length).toBe(0);
|
||||
|
@ -556,12 +556,12 @@ describe('list()', () => {
|
|||
|
||||
test('should return action variables context and empty state', () => {
|
||||
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
|
||||
registry.register(alertTypeWithVariables('x', 'c', ''));
|
||||
const alertType = registry.get('x');
|
||||
expect(alertType.actionVariables).toBeTruthy();
|
||||
registry.register(ruleTypeWithVariables('x', 'c', ''));
|
||||
const ruleType = registry.get('x');
|
||||
expect(ruleType.actionVariables).toBeTruthy();
|
||||
|
||||
const context = alertType.actionVariables!.context;
|
||||
const state = alertType.actionVariables!.state;
|
||||
const context = ruleType.actionVariables!.context;
|
||||
const state = ruleType.actionVariables!.state;
|
||||
|
||||
expect(state).toBeTruthy();
|
||||
expect(state!.length).toBe(0);
|
||||
|
@ -597,11 +597,11 @@ describe('ensureRuleTypeEnabled', () => {
|
|||
|
||||
test('should call ensureLicenseForAlertType on the license state', async () => {
|
||||
ruleTypeRegistry.ensureRuleTypeEnabled('test');
|
||||
expect(mockedLicenseState.ensureLicenseForAlertType).toHaveBeenCalled();
|
||||
expect(mockedLicenseState.ensureLicenseForRuleType).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should throw when ensureLicenseForAlertType throws', async () => {
|
||||
mockedLicenseState.ensureLicenseForAlertType.mockImplementation(() => {
|
||||
mockedLicenseState.ensureLicenseForRuleType.mockImplementation(() => {
|
||||
throw new Error('Fail');
|
||||
});
|
||||
expect(() => ruleTypeRegistry.ensureRuleTypeEnabled('test')).toThrowErrorMatchingInlineSnapshot(
|
||||
|
@ -610,12 +610,12 @@ describe('ensureRuleTypeEnabled', () => {
|
|||
});
|
||||
});
|
||||
|
||||
function alertTypeWithVariables<ActionGroupIds extends string>(
|
||||
function ruleTypeWithVariables<ActionGroupIds extends string>(
|
||||
id: ActionGroupIds,
|
||||
context: string,
|
||||
state: string
|
||||
): AlertType<never, never, never, never, never, ActionGroupIds> {
|
||||
const baseAlert: AlertType<never, never, never, never, never, ActionGroupIds> = {
|
||||
): RuleType<never, never, never, never, never, ActionGroupIds> {
|
||||
const baseAlert: RuleType<never, never, never, never, never, ActionGroupIds> = {
|
||||
id,
|
||||
name: `${id}-name`,
|
||||
actionGroups: [],
|
||||
|
|
|
@ -14,7 +14,7 @@ import { LicensingPluginSetup } from '../../licensing/server';
|
|||
import { RunContext, TaskManagerSetupContract } from '../../task_manager/server';
|
||||
import { TaskRunnerFactory } from './task_runner';
|
||||
import {
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
|
@ -28,7 +28,7 @@ import {
|
|||
validateDurationSchema,
|
||||
} from '../common';
|
||||
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 {
|
||||
taskManager: TaskManagerSetupContract;
|
||||
|
@ -39,7 +39,7 @@ export interface ConstructorOptions {
|
|||
|
||||
export interface RegistryRuleType
|
||||
extends Pick<
|
||||
UntypedNormalizedAlertType,
|
||||
UntypedNormalizedRuleType,
|
||||
| 'name'
|
||||
| 'actionGroups'
|
||||
| '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
|
||||
* 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.
|
||||
*/
|
||||
const alertIdSchema = schema.string({
|
||||
const ruleTypeIdSchema = schema.string({
|
||||
validate(value: string): string | void {
|
||||
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_\-\.]*$/)) {
|
||||
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?.join(`, `)}`;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export type NormalizedAlertType<
|
||||
export type NormalizedRuleType<
|
||||
Params extends AlertTypeParams,
|
||||
ExtractedParams extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
|
@ -87,7 +87,7 @@ export type NormalizedAlertType<
|
|||
> = {
|
||||
actionGroups: Array<ActionGroup<ActionGroupIds | RecoveryActionGroupId>>;
|
||||
} & Omit<
|
||||
AlertType<
|
||||
RuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -100,7 +100,7 @@ export type NormalizedAlertType<
|
|||
> &
|
||||
Pick<
|
||||
Required<
|
||||
AlertType<
|
||||
RuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -113,7 +113,7 @@ export type NormalizedAlertType<
|
|||
'recoveryActionGroup'
|
||||
>;
|
||||
|
||||
export type UntypedNormalizedAlertType = NormalizedAlertType<
|
||||
export type UntypedNormalizedRuleType = NormalizedRuleType<
|
||||
AlertTypeParams,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
|
@ -125,7 +125,7 @@ export type UntypedNormalizedAlertType = NormalizedAlertType<
|
|||
|
||||
export class RuleTypeRegistry {
|
||||
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 licenseState: ILicenseState;
|
||||
private readonly licensing: LicensingPluginSetup;
|
||||
|
@ -142,7 +142,7 @@ export class RuleTypeRegistry {
|
|||
}
|
||||
|
||||
public ensureRuleTypeEnabled(id: string) {
|
||||
this.licenseState.ensureLicenseForAlertType(this.get(id));
|
||||
this.licenseState.ensureLicenseForRuleType(this.get(id));
|
||||
}
|
||||
|
||||
public register<
|
||||
|
@ -154,7 +154,7 @@ export class RuleTypeRegistry {
|
|||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: AlertType<
|
||||
ruleType: RuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -164,44 +164,44 @@ export class RuleTypeRegistry {
|
|||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
if (this.has(alertType.id)) {
|
||||
if (this.has(ruleType.id)) {
|
||||
throw new Error(
|
||||
i18n.translate('xpack.alerting.ruleTypeRegistry.register.duplicateAlertTypeError', {
|
||||
i18n.translate('xpack.alerting.ruleTypeRegistry.register.duplicateRuleTypeError', {
|
||||
defaultMessage: 'Rule type "{id}" is already registered.',
|
||||
values: {
|
||||
id: alertType.id,
|
||||
id: ruleType.id,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
// validate ruleTypeTimeout here
|
||||
if (alertType.ruleTaskTimeout) {
|
||||
const invalidTimeout = validateDurationSchema(alertType.ruleTaskTimeout);
|
||||
if (ruleType.ruleTaskTimeout) {
|
||||
const invalidTimeout = validateDurationSchema(ruleType.ruleTaskTimeout);
|
||||
if (invalidTimeout) {
|
||||
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}.',
|
||||
values: {
|
||||
id: alertType.id,
|
||||
id: ruleType.id,
|
||||
errorMessage: invalidTimeout,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
alertType.actionVariables = normalizedActionVariables(alertType.actionVariables);
|
||||
ruleType.actionVariables = normalizedActionVariables(ruleType.actionVariables);
|
||||
|
||||
// validate defaultScheduleInterval here
|
||||
if (alertType.defaultScheduleInterval) {
|
||||
const invalidDefaultTimeout = validateDurationSchema(alertType.defaultScheduleInterval);
|
||||
if (ruleType.defaultScheduleInterval) {
|
||||
const invalidDefaultTimeout = validateDurationSchema(ruleType.defaultScheduleInterval);
|
||||
if (invalidDefaultTimeout) {
|
||||
throw new Error(
|
||||
i18n.translate(
|
||||
'xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutAlertTypeError',
|
||||
'xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutRuleTypeError',
|
||||
{
|
||||
defaultMessage: 'Rule type "{id}" has invalid default interval: {errorMessage}.',
|
||||
values: {
|
||||
id: alertType.id,
|
||||
id: ruleType.id,
|
||||
errorMessage: invalidDefaultTimeout,
|
||||
},
|
||||
}
|
||||
|
@ -211,16 +211,16 @@ export class RuleTypeRegistry {
|
|||
}
|
||||
|
||||
// validate minimumScheduleInterval here
|
||||
if (alertType.minimumScheduleInterval) {
|
||||
const invalidMinimumTimeout = validateDurationSchema(alertType.minimumScheduleInterval);
|
||||
if (ruleType.minimumScheduleInterval) {
|
||||
const invalidMinimumTimeout = validateDurationSchema(ruleType.minimumScheduleInterval);
|
||||
if (invalidMinimumTimeout) {
|
||||
throw new Error(
|
||||
i18n.translate(
|
||||
'xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutAlertTypeError',
|
||||
'xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutRuleTypeError',
|
||||
{
|
||||
defaultMessage: 'Rule type "{id}" has invalid minimum interval: {errorMessage}.',
|
||||
values: {
|
||||
id: alertType.id,
|
||||
id: ruleType.id,
|
||||
errorMessage: invalidMinimumTimeout,
|
||||
},
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ export class RuleTypeRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
const normalizedAlertType = augmentActionGroupsWithReserved<
|
||||
const normalizedRuleType = augmentActionGroupsWithReserved<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -237,17 +237,17 @@ export class RuleTypeRegistry {
|
|||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>(alertType);
|
||||
>(ruleType);
|
||||
|
||||
this.ruleTypes.set(
|
||||
alertIdSchema.validate(alertType.id),
|
||||
/** stripping the typing is required in order to store the AlertTypes in a Map */
|
||||
normalizedAlertType as unknown as UntypedNormalizedAlertType
|
||||
ruleTypeIdSchema.validate(ruleType.id),
|
||||
/** stripping the typing is required in order to store the RuleTypes in a Map */
|
||||
normalizedRuleType as unknown as UntypedNormalizedRuleType
|
||||
);
|
||||
this.taskManager.registerTaskDefinitions({
|
||||
[`alerting:${alertType.id}`]: {
|
||||
title: alertType.name,
|
||||
timeout: alertType.ruleTaskTimeout,
|
||||
[`alerting:${ruleType.id}`]: {
|
||||
title: ruleType.name,
|
||||
timeout: ruleType.ruleTaskTimeout,
|
||||
createTaskRunner: (context: RunContext) =>
|
||||
this.taskRunnerFactory.create<
|
||||
Params,
|
||||
|
@ -257,14 +257,14 @@ export class RuleTypeRegistry {
|
|||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId | RecoveredActionGroupId
|
||||
>(normalizedAlertType, context),
|
||||
>(normalizedRuleType, context),
|
||||
},
|
||||
});
|
||||
// No need to notify usage on basic alert types
|
||||
if (alertType.minimumLicenseRequired !== 'basic') {
|
||||
if (ruleType.minimumLicenseRequired !== 'basic') {
|
||||
this.licensing.featureUsage.register(
|
||||
getAlertTypeFeatureUsageName(alertType.name),
|
||||
alertType.minimumLicenseRequired
|
||||
getRuleTypeFeatureUsageName(ruleType.name),
|
||||
ruleType.minimumLicenseRequired
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ export class RuleTypeRegistry {
|
|||
RecoveryActionGroupId extends string = string
|
||||
>(
|
||||
id: string
|
||||
): NormalizedAlertType<
|
||||
): NormalizedRuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -290,7 +290,7 @@ export class RuleTypeRegistry {
|
|||
> {
|
||||
if (!this.has(id)) {
|
||||
throw Boom.badRequest(
|
||||
i18n.translate('xpack.alerting.ruleTypeRegistry.get.missingAlertTypeError', {
|
||||
i18n.translate('xpack.alerting.ruleTypeRegistry.get.missingRuleTypeError', {
|
||||
defaultMessage: 'Rule type "{id}" is not registered.',
|
||||
values: {
|
||||
id,
|
||||
|
@ -299,11 +299,11 @@ export class RuleTypeRegistry {
|
|||
);
|
||||
}
|
||||
/**
|
||||
* When we store the AlertTypes in the Map we strip the typing.
|
||||
* This means that returning a typed AlertType in `get` is an inherently
|
||||
* When we store the RuleTypes in the Map we strip the typing.
|
||||
* 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.
|
||||
*/
|
||||
return this.ruleTypes.get(id)! as unknown as NormalizedAlertType<
|
||||
return this.ruleTypes.get(id)! as unknown as NormalizedRuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -332,7 +332,7 @@ export class RuleTypeRegistry {
|
|||
minimumScheduleInterval,
|
||||
defaultScheduleInterval,
|
||||
},
|
||||
]: [string, UntypedNormalizedAlertType]) => ({
|
||||
]: [string, UntypedNormalizedRuleType]) => ({
|
||||
id,
|
||||
name,
|
||||
actionGroups,
|
||||
|
@ -345,7 +345,7 @@ export class RuleTypeRegistry {
|
|||
ruleTaskTimeout,
|
||||
minimumScheduleInterval,
|
||||
defaultScheduleInterval,
|
||||
enabledInLicense: !!this.licenseState.getLicenseCheckForAlertType(
|
||||
enabledInLicense: !!this.licenseState.getLicenseCheckForRuleType(
|
||||
id,
|
||||
name,
|
||||
minimumLicenseRequired
|
||||
|
@ -356,7 +356,7 @@ export class RuleTypeRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
function normalizedActionVariables(actionVariables: AlertType['actionVariables']) {
|
||||
function normalizedActionVariables(actionVariables: RuleType['actionVariables']) {
|
||||
return {
|
||||
context: actionVariables?.context ?? [],
|
||||
state: actionVariables?.state ?? [],
|
||||
|
@ -373,7 +373,7 @@ function augmentActionGroupsWithReserved<
|
|||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: AlertType<
|
||||
ruleType: RuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -382,7 +382,7 @@ function augmentActionGroupsWithReserved<
|
|||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
): NormalizedAlertType<
|
||||
): NormalizedRuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -391,8 +391,8 @@ function augmentActionGroupsWithReserved<
|
|||
ActionGroupIds,
|
||||
RecoveredActionGroupId | RecoveryActionGroupId
|
||||
> {
|
||||
const reservedActionGroups = getBuiltinActionGroups(alertType.recoveryActionGroup);
|
||||
const { id, actionGroups, recoveryActionGroup } = alertType;
|
||||
const reservedActionGroups = getBuiltinActionGroups(ruleType.recoveryActionGroup);
|
||||
const { id, actionGroups, recoveryActionGroup } = ruleType;
|
||||
|
||||
const activeActionGroups = new Set<string>(actionGroups.map((item) => item.id));
|
||||
const intersectingReservedActionGroups = intersection<string>(
|
||||
|
@ -427,7 +427,7 @@ function augmentActionGroupsWithReserved<
|
|||
}
|
||||
|
||||
return {
|
||||
...alertType,
|
||||
...ruleType,
|
||||
actionGroups: [...actionGroups, ...reservedActionGroups],
|
||||
recoveryActionGroup: recoveryActionGroup ?? RecoveredActionGroup,
|
||||
};
|
||||
|
|
|
@ -24,27 +24,23 @@ import { ActionsClient, ActionsAuthorization } from '../../../actions/server';
|
|||
import {
|
||||
Alert,
|
||||
PartialAlert,
|
||||
RawAlert,
|
||||
RawRule,
|
||||
RuleTypeRegistry,
|
||||
AlertAction,
|
||||
IntervalSchedule,
|
||||
SanitizedAlert,
|
||||
AlertTaskState,
|
||||
RuleTaskState,
|
||||
AlertSummary,
|
||||
AlertExecutionStatusValues,
|
||||
AlertNotifyWhenType,
|
||||
AlertTypeParams,
|
||||
ResolvedSanitizedRule,
|
||||
AlertWithLegacyId,
|
||||
SanitizedAlertWithLegacyId,
|
||||
SanitizedRuleWithLegacyId,
|
||||
PartialAlertWithLegacyId,
|
||||
RawAlertInstance,
|
||||
} from '../types';
|
||||
import {
|
||||
validateAlertTypeParams,
|
||||
alertExecutionStatusFromRaw,
|
||||
getAlertNotifyWhenType,
|
||||
} from '../lib';
|
||||
import { validateRuleTypeParams, ruleExecutionStatusFromRaw, getAlertNotifyWhenType } from '../lib';
|
||||
import {
|
||||
GrantAPIKeyResult as SecurityPluginGrantAPIKeyResult,
|
||||
InvalidateAPIKeyResult as SecurityPluginInvalidateAPIKeyResult,
|
||||
|
@ -52,7 +48,7 @@ import {
|
|||
import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server';
|
||||
import { TaskManagerStartContract } from '../../../task_manager/server';
|
||||
import { taskInstanceToAlertTaskInstance } from '../task_runner/alert_task_instance';
|
||||
import { RegistryRuleType, UntypedNormalizedAlertType } from '../rule_type_registry';
|
||||
import { RegistryRuleType, UntypedNormalizedRuleType } from '../rule_type_registry';
|
||||
import {
|
||||
AlertingAuthorization,
|
||||
WriteOperations,
|
||||
|
@ -77,7 +73,7 @@ import { markApiKeyForInvalidation } from '../invalidate_pending_api_keys/mark_a
|
|||
import { ruleAuditEvent, RuleAuditAction } from './audit_events';
|
||||
import { KueryNode, nodeBuilder } from '../../../../../src/plugins/data/common';
|
||||
import { mapSortField } from './lib';
|
||||
import { getAlertExecutionStatusPending } from '../lib/alert_execution_status';
|
||||
import { getRuleExecutionStatusPending } from '../lib/rule_execution_status';
|
||||
import { AlertInstance } from '../alert_instance';
|
||||
import { EVENT_LOG_ACTIONS } from '../plugin';
|
||||
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
|
||||
const ruleType = this.ruleTypeRegistry.get(data.alertTypeId);
|
||||
|
||||
const validatedAlertTypeParams = validateAlertTypeParams(
|
||||
data.params,
|
||||
ruleType.validate?.params
|
||||
);
|
||||
const validatedAlertTypeParams = validateRuleTypeParams(data.params, ruleType.validate?.params);
|
||||
const username = await this.getUserName();
|
||||
|
||||
let createdAPIKey = null;
|
||||
|
@ -355,7 +348,7 @@ export class RulesClient {
|
|||
const legacyId = Semver.lt(this.kibanaVersion, '8.0.0') ? id : null;
|
||||
const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle);
|
||||
|
||||
const rawAlert: RawAlert = {
|
||||
const rawRule: RawRule = {
|
||||
...data,
|
||||
...this.apiKeyAsAlertAttributes(createdAPIKey, username),
|
||||
legacyId,
|
||||
|
@ -364,11 +357,11 @@ export class RulesClient {
|
|||
updatedBy: username,
|
||||
createdAt: new Date(createTime).toISOString(),
|
||||
updatedAt: new Date(createTime).toISOString(),
|
||||
params: updatedParams as RawAlert['params'],
|
||||
params: updatedParams as RawRule['params'],
|
||||
muteAll: false,
|
||||
mutedInstanceIds: [],
|
||||
notifyWhen,
|
||||
executionStatus: getAlertExecutionStatusPending(new Date().toISOString()),
|
||||
executionStatus: getRuleExecutionStatusPending(new Date().toISOString()),
|
||||
};
|
||||
|
||||
this.auditLogger?.log(
|
||||
|
@ -379,11 +372,11 @@ export class RulesClient {
|
|||
})
|
||||
);
|
||||
|
||||
let createdAlert: SavedObject<RawAlert>;
|
||||
let createdAlert: SavedObject<RawRule>;
|
||||
try {
|
||||
createdAlert = await this.unsecuredSavedObjectsClient.create(
|
||||
'alert',
|
||||
this.updateMeta(rawAlert),
|
||||
this.updateMeta(rawRule),
|
||||
{
|
||||
...options,
|
||||
references,
|
||||
|
@ -393,7 +386,7 @@ export class RulesClient {
|
|||
} catch (e) {
|
||||
// Avoid unused API key
|
||||
markApiKeyForInvalidation(
|
||||
{ apiKey: rawAlert.apiKey },
|
||||
{ apiKey: rawRule.apiKey },
|
||||
this.logger,
|
||||
this.unsecuredSavedObjectsClient
|
||||
);
|
||||
|
@ -404,7 +397,7 @@ export class RulesClient {
|
|||
try {
|
||||
scheduledTask = await this.scheduleRule(
|
||||
createdAlert.id,
|
||||
rawAlert.alertTypeId,
|
||||
rawRule.alertTypeId,
|
||||
data.schedule,
|
||||
true
|
||||
);
|
||||
|
@ -420,7 +413,7 @@ export class RulesClient {
|
|||
}
|
||||
throw e;
|
||||
}
|
||||
await this.unsecuredSavedObjectsClient.update<RawAlert>('alert', createdAlert.id, {
|
||||
await this.unsecuredSavedObjectsClient.update<RawRule>('alert', createdAlert.id, {
|
||||
scheduledTaskId: scheduledTask.id,
|
||||
});
|
||||
createdAlert.attributes.scheduledTaskId = scheduledTask.id;
|
||||
|
@ -439,8 +432,8 @@ export class RulesClient {
|
|||
}: {
|
||||
id: string;
|
||||
includeLegacyId?: boolean;
|
||||
}): Promise<SanitizedAlert<Params> | SanitizedAlertWithLegacyId<Params>> {
|
||||
const result = await this.unsecuredSavedObjectsClient.get<RawAlert>('alert', id);
|
||||
}): Promise<SanitizedAlert<Params> | SanitizedRuleWithLegacyId<Params>> {
|
||||
const result = await this.unsecuredSavedObjectsClient.get<RawRule>('alert', id);
|
||||
try {
|
||||
await this.authorization.ensureAuthorized({
|
||||
ruleTypeId: result.attributes.alertTypeId,
|
||||
|
@ -481,7 +474,7 @@ export class RulesClient {
|
|||
includeLegacyId?: boolean;
|
||||
}): Promise<ResolvedSanitizedRule<Params>> {
|
||||
const { saved_object: result, ...resolveResponse } =
|
||||
await this.unsecuredSavedObjectsClient.resolve<RawAlert>('alert', id);
|
||||
await this.unsecuredSavedObjectsClient.resolve<RawRule>('alert', id);
|
||||
try {
|
||||
await this.authorization.ensureAuthorized({
|
||||
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 });
|
||||
await this.authorization.ensureAuthorized({
|
||||
ruleTypeId: alert.alertTypeId,
|
||||
|
@ -539,7 +532,7 @@ export class RulesClient {
|
|||
|
||||
public async getAlertSummary({ id, dateStart }: GetAlertSummaryParams): Promise<AlertSummary> {
|
||||
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({
|
||||
ruleTypeId: rule.alertTypeId,
|
||||
|
@ -612,7 +605,7 @@ export class RulesClient {
|
|||
per_page: perPage,
|
||||
total,
|
||||
saved_objects: data,
|
||||
} = await this.unsecuredSavedObjectsClient.find<RawAlert>({
|
||||
} = await this.unsecuredSavedObjectsClient.find<RawRule>({
|
||||
...options,
|
||||
sortField: mapSortField(options.sortField),
|
||||
filter:
|
||||
|
@ -646,7 +639,7 @@ export class RulesClient {
|
|||
return this.getAlertFromRaw<Params>(
|
||||
id,
|
||||
attributes.alertTypeId,
|
||||
fields ? (pick(attributes, fields) as RawAlert) : attributes,
|
||||
fields ? (pick(attributes, fields) as RawRule) : attributes,
|
||||
references
|
||||
);
|
||||
});
|
||||
|
@ -687,7 +680,7 @@ export class RulesClient {
|
|||
throw error;
|
||||
}
|
||||
const { filter: authorizationFilter } = authorizationTuple;
|
||||
const resp = await this.unsecuredSavedObjectsClient.find<RawAlert, RuleAggregation>({
|
||||
const resp = await this.unsecuredSavedObjectsClient.find<RawRule, RuleAggregation>({
|
||||
...options,
|
||||
filter:
|
||||
(authorizationFilter && filter
|
||||
|
@ -776,11 +769,11 @@ export class RulesClient {
|
|||
private async deleteWithOCC({ id }: { id: string }) {
|
||||
let taskIdToRemove: string | undefined | null;
|
||||
let apiKeyToInvalidate: string | null = null;
|
||||
let attributes: RawAlert;
|
||||
let attributes: RawRule;
|
||||
|
||||
try {
|
||||
const decryptedAlert =
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, {
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
|
||||
namespace: this.namespace,
|
||||
});
|
||||
apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
|
||||
|
@ -792,7 +785,7 @@ export class RulesClient {
|
|||
`delete(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
|
||||
);
|
||||
// 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;
|
||||
attributes = alert.attributes;
|
||||
}
|
||||
|
@ -854,20 +847,23 @@ export class RulesClient {
|
|||
id,
|
||||
data,
|
||||
}: UpdateOptions<Params>): Promise<PartialAlert<Params>> {
|
||||
let alertSavedObject: SavedObject<RawAlert>;
|
||||
let alertSavedObject: SavedObject<RawRule>;
|
||||
|
||||
try {
|
||||
alertSavedObject =
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, {
|
||||
alertSavedObject = await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>(
|
||||
'alert',
|
||||
id,
|
||||
{
|
||||
namespace: this.namespace,
|
||||
});
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
// We'll skip invalidating the API key since we failed to load the decrypted saved object
|
||||
this.logger.error(
|
||||
`update(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
|
||||
);
|
||||
// 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 {
|
||||
|
@ -934,15 +930,12 @@ export class RulesClient {
|
|||
|
||||
private async updateAlert<Params extends AlertTypeParams>(
|
||||
{ id, data }: UpdateOptions<Params>,
|
||||
{ attributes, version }: SavedObject<RawAlert>
|
||||
{ attributes, version }: SavedObject<RawRule>
|
||||
): Promise<PartialAlert<Params>> {
|
||||
const ruleType = this.ruleTypeRegistry.get(attributes.alertTypeId);
|
||||
|
||||
// Validate
|
||||
const validatedAlertTypeParams = validateAlertTypeParams(
|
||||
data.params,
|
||||
ruleType.validate?.params
|
||||
);
|
||||
const validatedAlertTypeParams = validateRuleTypeParams(data.params, ruleType.validate?.params);
|
||||
await this.validateActions(ruleType, data.actions);
|
||||
|
||||
// Validate intervals, if configured
|
||||
|
@ -977,19 +970,19 @@ export class RulesClient {
|
|||
const apiKeyAttributes = this.apiKeyAsAlertAttributes(createdAPIKey, username);
|
||||
const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle);
|
||||
|
||||
let updatedObject: SavedObject<RawAlert>;
|
||||
let updatedObject: SavedObject<RawRule>;
|
||||
const createAttributes = this.updateMeta({
|
||||
...attributes,
|
||||
...data,
|
||||
...apiKeyAttributes,
|
||||
params: updatedParams as RawAlert['params'],
|
||||
params: updatedParams as RawRule['params'],
|
||||
actions,
|
||||
notifyWhen,
|
||||
updatedBy: username,
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
try {
|
||||
updatedObject = await this.unsecuredSavedObjectsClient.create<RawAlert>(
|
||||
updatedObject = await this.unsecuredSavedObjectsClient.create<RawRule>(
|
||||
'alert',
|
||||
createAttributes,
|
||||
{
|
||||
|
@ -1020,7 +1013,7 @@ export class RulesClient {
|
|||
private apiKeyAsAlertAttributes(
|
||||
apiKey: CreateAPIKeyResult | null,
|
||||
username: string | null
|
||||
): Pick<RawAlert, 'apiKey' | 'apiKeyOwner'> {
|
||||
): Pick<RawRule, 'apiKey' | 'apiKeyOwner'> {
|
||||
return apiKey && apiKey.apiKeysEnabled
|
||||
? {
|
||||
apiKeyOwner: username,
|
||||
|
@ -1042,12 +1035,12 @@ export class RulesClient {
|
|||
|
||||
private async updateApiKeyWithOCC({ id }: { id: string }) {
|
||||
let apiKeyToInvalidate: string | null = null;
|
||||
let attributes: RawAlert;
|
||||
let attributes: RawRule;
|
||||
let version: string | undefined;
|
||||
|
||||
try {
|
||||
const decryptedAlert =
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, {
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
|
||||
namespace: this.namespace,
|
||||
});
|
||||
apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
|
||||
|
@ -1059,7 +1052,7 @@ export class RulesClient {
|
|||
`updateApiKey(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
|
||||
);
|
||||
// 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;
|
||||
version = alert.version;
|
||||
}
|
||||
|
@ -1146,12 +1139,12 @@ export class RulesClient {
|
|||
|
||||
private async enableWithOCC({ id }: { id: string }) {
|
||||
let apiKeyToInvalidate: string | null = null;
|
||||
let attributes: RawAlert;
|
||||
let attributes: RawRule;
|
||||
let version: string | undefined;
|
||||
|
||||
try {
|
||||
const decryptedAlert =
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, {
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
|
||||
namespace: this.namespace,
|
||||
});
|
||||
apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
|
||||
|
@ -1163,7 +1156,7 @@ export class RulesClient {
|
|||
`enable(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
|
||||
);
|
||||
// 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;
|
||||
version = alert.version;
|
||||
}
|
||||
|
@ -1265,12 +1258,12 @@ export class RulesClient {
|
|||
|
||||
private async disableWithOCC({ id }: { id: string }) {
|
||||
let apiKeyToInvalidate: string | null = null;
|
||||
let attributes: RawAlert;
|
||||
let attributes: RawRule;
|
||||
let version: string | undefined;
|
||||
|
||||
try {
|
||||
const decryptedAlert =
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>('alert', id, {
|
||||
await this.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>('alert', id, {
|
||||
namespace: this.namespace,
|
||||
});
|
||||
apiKeyToInvalidate = decryptedAlert.attributes.apiKey;
|
||||
|
@ -1282,7 +1275,7 @@ export class RulesClient {
|
|||
`disable(): Failed to load API key to invalidate on alert ${id}: ${e.message}`
|
||||
);
|
||||
// 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;
|
||||
version = alert.version;
|
||||
}
|
||||
|
@ -1403,7 +1396,7 @@ export class RulesClient {
|
|||
}
|
||||
|
||||
private async muteAllWithOCC({ id }: { id: string }) {
|
||||
const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawAlert>(
|
||||
const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawRule>(
|
||||
'alert',
|
||||
id
|
||||
);
|
||||
|
@ -1465,7 +1458,7 @@ export class RulesClient {
|
|||
}
|
||||
|
||||
private async unmuteAllWithOCC({ id }: { id: string }) {
|
||||
const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawAlert>(
|
||||
const { attributes, version } = await this.unsecuredSavedObjectsClient.get<RawRule>(
|
||||
'alert',
|
||||
id
|
||||
);
|
||||
|
@ -1633,7 +1626,7 @@ export class RulesClient {
|
|||
|
||||
const mutedInstanceIds = attributes.mutedInstanceIds || [];
|
||||
if (!attributes.muteAll && mutedInstanceIds.includes(alertInstanceId)) {
|
||||
await this.unsecuredSavedObjectsClient.update<RawAlert>(
|
||||
await this.unsecuredSavedObjectsClient.update<RawRule>(
|
||||
'alert',
|
||||
alertId,
|
||||
this.updateMeta({
|
||||
|
@ -1691,7 +1684,7 @@ export class RulesClient {
|
|||
|
||||
private injectReferencesIntoActions(
|
||||
alertId: string,
|
||||
actions: RawAlert['actions'],
|
||||
actions: RawRule['actions'],
|
||||
references: SavedObjectReference[]
|
||||
) {
|
||||
return actions.map((action) => {
|
||||
|
@ -1716,18 +1709,18 @@ export class RulesClient {
|
|||
private getAlertFromRaw<Params extends AlertTypeParams>(
|
||||
id: string,
|
||||
ruleTypeId: string,
|
||||
rawAlert: RawAlert,
|
||||
rawRule: RawRule,
|
||||
references: SavedObjectReference[] | undefined,
|
||||
includeLegacyId: boolean = false
|
||||
): Alert | AlertWithLegacyId {
|
||||
const ruleType = this.ruleTypeRegistry.get(ruleTypeId);
|
||||
// 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
|
||||
const res = this.getPartialAlertFromRaw<Params>(
|
||||
id,
|
||||
ruleType,
|
||||
rawAlert,
|
||||
rawRule,
|
||||
references,
|
||||
includeLegacyId
|
||||
);
|
||||
|
@ -1741,7 +1734,7 @@ export class RulesClient {
|
|||
|
||||
private getPartialAlertFromRaw<Params extends AlertTypeParams>(
|
||||
id: string,
|
||||
ruleType: UntypedNormalizedAlertType,
|
||||
ruleType: UntypedNormalizedRuleType,
|
||||
{
|
||||
createdAt,
|
||||
updatedAt,
|
||||
|
@ -1753,15 +1746,15 @@ export class RulesClient {
|
|||
executionStatus,
|
||||
schedule,
|
||||
actions,
|
||||
...partialRawAlert
|
||||
}: Partial<RawAlert>,
|
||||
...partialRawRule
|
||||
}: Partial<RawRule>,
|
||||
references: SavedObjectReference[] | undefined,
|
||||
includeLegacyId: boolean = false
|
||||
): PartialAlert<Params> | PartialAlertWithLegacyId<Params> {
|
||||
const rule = {
|
||||
id,
|
||||
notifyWhen,
|
||||
...partialRawAlert,
|
||||
...partialRawRule,
|
||||
// we currently only support the Interval Schedule type
|
||||
// Once we support additional types, this type signature will likely change
|
||||
schedule: schedule as IntervalSchedule,
|
||||
|
@ -1771,7 +1764,7 @@ export class RulesClient {
|
|||
...(createdAt ? { createdAt: new Date(createdAt) } : {}),
|
||||
...(scheduledTaskId ? { scheduledTaskId } : {}),
|
||||
...(executionStatus
|
||||
? { executionStatus: alertExecutionStatusFromRaw(this.logger, id, executionStatus) }
|
||||
? { executionStatus: ruleExecutionStatusFromRaw(this.logger, id, executionStatus) }
|
||||
: {}),
|
||||
};
|
||||
return includeLegacyId
|
||||
|
@ -1780,7 +1773,7 @@ export class RulesClient {
|
|||
}
|
||||
|
||||
private async validateActions(
|
||||
alertType: UntypedNormalizedAlertType,
|
||||
alertType: UntypedNormalizedRuleType,
|
||||
actions: NormalizedAlertAction[]
|
||||
): Promise<void> {
|
||||
if (actions.length === 0) {
|
||||
|
@ -1831,11 +1824,11 @@ export class RulesClient {
|
|||
Params extends AlertTypeParams,
|
||||
ExtractedParams extends AlertTypeParams
|
||||
>(
|
||||
ruleType: UntypedNormalizedAlertType,
|
||||
ruleType: UntypedNormalizedRuleType,
|
||||
ruleActions: NormalizedAlertAction[],
|
||||
ruleParams: Params
|
||||
): Promise<{
|
||||
actions: RawAlert['actions'];
|
||||
actions: RawRule['actions'];
|
||||
params: ExtractedParams;
|
||||
references: SavedObjectReference[];
|
||||
}> {
|
||||
|
@ -1868,7 +1861,7 @@ export class RulesClient {
|
|||
ExtractedParams extends AlertTypeParams
|
||||
>(
|
||||
ruleId: string,
|
||||
ruleType: UntypedNormalizedAlertType,
|
||||
ruleType: UntypedNormalizedRuleType,
|
||||
ruleParams: SavedObjectAttributes | undefined,
|
||||
references: SavedObjectReference[]
|
||||
): Params {
|
||||
|
@ -1896,9 +1889,9 @@ export class RulesClient {
|
|||
|
||||
private async denormalizeActions(
|
||||
alertActions: NormalizedAlertAction[]
|
||||
): Promise<{ actions: RawAlert['actions']; references: SavedObjectReference[] }> {
|
||||
): Promise<{ actions: RawRule['actions']; references: SavedObjectReference[] }> {
|
||||
const references: SavedObjectReference[] = [];
|
||||
const actions: RawAlert['actions'] = [];
|
||||
const actions: RawRule['actions'] = [];
|
||||
if (alertActions.length) {
|
||||
const actionsClient = await this.getActionsClient();
|
||||
const actionIds = [...new Set(alertActions.map((alertAction) => alertAction.id))];
|
||||
|
@ -1953,7 +1946,7 @@ export class RulesClient {
|
|||
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')) {
|
||||
alertAttributes.meta = alertAttributes.meta ?? {};
|
||||
alertAttributes.meta.versionApiKeyLastmodified = this.kibanaVersion;
|
||||
|
|
|
@ -19,7 +19,7 @@ import { eventLogClientMock } from '../../../../event_log/server/mocks';
|
|||
import { QueryEventsBySavedObjectResult } from '../../../../event_log/server';
|
||||
import { SavedObject } from 'kibana/server';
|
||||
import { EventsFactory } from '../../lib/alert_summary_from_event_log.test';
|
||||
import { RawAlert } from '../../types';
|
||||
import { RawRule } from '../../types';
|
||||
import { getBeforeSetup, mockedDateString, setGlobalDate } from './lib';
|
||||
|
||||
const taskManager = taskManagerMock.createStart();
|
||||
|
@ -64,7 +64,7 @@ const AlertSummaryFindEventsResult: QueryEventsBySavedObjectResult = {
|
|||
|
||||
const RuleIntervalSeconds = 1;
|
||||
|
||||
const BaseRuleSavedObject: SavedObject<RawAlert> = {
|
||||
const BaseRuleSavedObject: SavedObject<RawRule> = {
|
||||
id: '1',
|
||||
type: 'alert',
|
||||
attributes: {
|
||||
|
@ -96,7 +96,7 @@ const BaseRuleSavedObject: SavedObject<RawAlert> = {
|
|||
references: [],
|
||||
};
|
||||
|
||||
function getRuleSavedObject(attributes: Partial<RawAlert> = {}): SavedObject<RawAlert> {
|
||||
function getRuleSavedObject(attributes: Partial<RawRule> = {}): SavedObject<RawRule> {
|
||||
return {
|
||||
...BaseRuleSavedObject,
|
||||
attributes: { ...BaseRuleSavedObject.attributes, ...attributes },
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
} from 'kibana/server';
|
||||
import { AlertTypeParams } from '../../index';
|
||||
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
|
||||
// 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(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
if (doc.attributes.alertTypeId !== GEO_CONTAINMENT_ID) {
|
||||
return doc;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { SavedObject } from 'kibana/server';
|
||||
import { RawAlert } from '../types';
|
||||
import { RawRule } from '../types';
|
||||
import { getImportWarnings } from './get_import_warnings';
|
||||
|
||||
describe('getImportWarnings', () => {
|
||||
|
@ -71,13 +71,13 @@ describe('getImportWarnings', () => {
|
|||
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.');
|
||||
});
|
||||
|
||||
it('return no warning messages if no rules were imported', () => {
|
||||
const savedObjectRules = [] as Array<SavedObject<RawAlert>>;
|
||||
const warnings = getImportWarnings(savedObjectRules as unknown as Array<SavedObject<RawAlert>>);
|
||||
const savedObjectRules = [] as Array<SavedObject<RawRule>>;
|
||||
const warnings = getImportWarnings(savedObjectRules as unknown as Array<SavedObject<RawRule>>);
|
||||
expect(warnings.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@ import mappings from './mappings.json';
|
|||
import { getMigrations } from './migrations';
|
||||
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
|
||||
import { transformRulesForExport } from './transform_rule_for_export';
|
||||
import { RawAlert } from '../types';
|
||||
import { RawRule } from '../types';
|
||||
import { getImportWarnings } from './get_import_warnings';
|
||||
import { isRuleExportable } from './is_rule_exportable';
|
||||
import { RuleTypeRegistry } from '../rule_type_registry';
|
||||
|
@ -60,7 +60,7 @@ export function setupSavedObjects(
|
|||
management: {
|
||||
displayName: 'rule',
|
||||
importableAndExportable: true,
|
||||
getTitle(ruleSavedObject: SavedObject<RawAlert>) {
|
||||
getTitle(ruleSavedObject: SavedObject<RawRule>) {
|
||||
return `Rule: [${ruleSavedObject.attributes.name}]`;
|
||||
},
|
||||
onImport(ruleSavedObjects) {
|
||||
|
@ -68,13 +68,13 @@ export function setupSavedObjects(
|
|||
warnings: getImportWarnings(ruleSavedObjects),
|
||||
};
|
||||
},
|
||||
onExport<RawAlert>(
|
||||
onExport<RawRule>(
|
||||
context: SavedObjectsExportTransformContext,
|
||||
objects: Array<SavedObject<RawAlert>>
|
||||
objects: Array<SavedObject<RawRule>>
|
||||
) {
|
||||
return transformRulesForExport(objects);
|
||||
},
|
||||
isExportable<RawAlert>(ruleSavedObject: SavedObject<RawAlert>) {
|
||||
isExportable<RawRule>(ruleSavedObject: SavedObject<RawRule>) {
|
||||
return isRuleExportable(ruleSavedObject, ruleTypeRegistry, logger);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { Logger, SavedObject } from 'kibana/server';
|
||||
import { RawAlert } from '../types';
|
||||
import { RawRule } from '../types';
|
||||
import { RuleTypeRegistry } from '../rule_type_registry';
|
||||
|
||||
export function isRuleExportable(
|
||||
|
@ -14,7 +14,7 @@ export function isRuleExportable(
|
|||
ruleTypeRegistry: RuleTypeRegistry,
|
||||
logger: Logger
|
||||
): boolean {
|
||||
const ruleSO = rule as SavedObject<RawAlert>;
|
||||
const ruleSO = rule as SavedObject<RawRule>;
|
||||
try {
|
||||
const ruleType = ruleTypeRegistry.get(ruleSO.attributes.alertTypeId);
|
||||
if (!ruleType.isExportable) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import uuid from 'uuid';
|
||||
import { getMigrations, isAnyActionSupportIncidents } from './migrations';
|
||||
import { RawAlert } from '../types';
|
||||
import { RawRule } from '../types';
|
||||
import { SavedObjectUnsanitizedDoc } from 'kibana/server';
|
||||
import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks';
|
||||
import { migrationMocks } from 'src/core/server/mocks';
|
||||
|
@ -512,7 +512,7 @@ describe('successful migrations', () => {
|
|||
(actionTypeId) => {
|
||||
const doc = {
|
||||
attributes: { actions: [{ actionTypeId }, { actionTypeId: '.server-log' }] },
|
||||
} as SavedObjectUnsanitizedDoc<RawAlert>;
|
||||
} as SavedObjectUnsanitizedDoc<RawRule>;
|
||||
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', () => {
|
||||
const doc = {
|
||||
attributes: { actions: [{ actionTypeId: '.server-log' }] },
|
||||
} as SavedObjectUnsanitizedDoc<RawAlert>;
|
||||
} as SavedObjectUnsanitizedDoc<RawRule>;
|
||||
expect(isAnyActionSupportIncidents(doc)).toBe(false);
|
||||
});
|
||||
|
||||
|
@ -2254,7 +2254,7 @@ function getUpdatedAt(): string {
|
|||
function getMockData(
|
||||
overwrites: Record<string, unknown> = {},
|
||||
withSavedObjectUpdatedAt: boolean = false
|
||||
): SavedObjectUnsanitizedDoc<Partial<RawAlert>> {
|
||||
): SavedObjectUnsanitizedDoc<Partial<RawRule>> {
|
||||
return {
|
||||
attributes: {
|
||||
enabled: true,
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
SavedObjectAttribute,
|
||||
SavedObjectReference,
|
||||
} from '../../../../../src/core/server';
|
||||
import { RawAlert, RawAlertAction } from '../types';
|
||||
import { RawRule, RawAlertAction } from '../types';
|
||||
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
|
||||
import type { IsMigrationNeededPredicate } from '../../../encrypted_saved_objects/server';
|
||||
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';
|
||||
|
||||
interface AlertLogMeta extends LogMeta {
|
||||
migrations: { alertDocument: SavedObjectUnsanitizedDoc<RawAlert> };
|
||||
migrations: { alertDocument: SavedObjectUnsanitizedDoc<RawRule> };
|
||||
}
|
||||
|
||||
type AlertMigration = (
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
) => SavedObjectUnsanitizedDoc<RawAlert>;
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
) => SavedObjectUnsanitizedDoc<RawRule>;
|
||||
|
||||
function createEsoMigration(
|
||||
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup,
|
||||
isMigrationNeededPredicate: IsMigrationNeededPredicate<RawAlert, RawAlert>,
|
||||
isMigrationNeededPredicate: IsMigrationNeededPredicate<RawRule, RawRule>,
|
||||
migrationFunc: AlertMigration
|
||||
) {
|
||||
return encryptedSavedObjects.createMigration<RawAlert, RawAlert>({
|
||||
return encryptedSavedObjects.createMigration<RawRule, RawRule>({
|
||||
isMigrationNeededPredicate,
|
||||
migration: migrationFunc,
|
||||
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'];
|
||||
|
||||
export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc<RawAlert>): boolean =>
|
||||
export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc<RawRule>): boolean =>
|
||||
doc.attributes.actions.some((action) =>
|
||||
SUPPORT_INCIDENTS_ACTION_TYPES.includes(action.actionTypeId)
|
||||
);
|
||||
|
||||
// Deprecated in 8.0
|
||||
export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc<RawAlert>): boolean =>
|
||||
export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc<RawRule>): boolean =>
|
||||
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
|
||||
*/
|
||||
export const isSecuritySolutionLegacyNotification = (
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): boolean => doc.attributes.alertTypeId === 'siem.notifications';
|
||||
|
||||
export function getMigrations(
|
||||
|
@ -76,7 +76,7 @@ export function getMigrations(
|
|||
const migrationWhenRBACWasIntroduced = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
// 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(
|
||||
markAsLegacyAndChangeConsumer,
|
||||
setAlertIdAsDefaultDedupkeyOnPagerDutyActions,
|
||||
|
@ -87,37 +87,37 @@ export function getMigrations(
|
|||
const migrationAlertUpdatedAtAndNotifyWhen = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
// 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)
|
||||
);
|
||||
|
||||
const migrationActions7112 = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isAnyActionSupportIncidents(doc),
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isAnyActionSupportIncidents(doc),
|
||||
pipeMigrations(restructureConnectorsThatSupportIncident)
|
||||
);
|
||||
|
||||
const migrationSecurityRules713 = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isSiemSignalsRuleType(doc),
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isSiemSignalsRuleType(doc),
|
||||
pipeMigrations(removeNullsFromSecurityRules)
|
||||
);
|
||||
|
||||
const migrationSecurityRules714 = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isSiemSignalsRuleType(doc),
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isSiemSignalsRuleType(doc),
|
||||
pipeMigrations(removeNullAuthorFromSecurityRules)
|
||||
);
|
||||
|
||||
const migrationSecurityRules715 = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => isSiemSignalsRuleType(doc),
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawRule> => isSiemSignalsRuleType(doc),
|
||||
pipeMigrations(addExceptionListsToReferences)
|
||||
);
|
||||
|
||||
const migrateRules716 = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawAlert> => true,
|
||||
(doc): doc is SavedObjectUnsanitizedDoc<RawRule> => true,
|
||||
pipeMigrations(
|
||||
setLegacyId,
|
||||
getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured),
|
||||
|
@ -128,7 +128,7 @@ export function getMigrations(
|
|||
|
||||
const migrationRules800 = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
(doc: SavedObjectUnsanitizedDoc<RawAlert>): doc is SavedObjectUnsanitizedDoc<RawAlert> => true,
|
||||
(doc: SavedObjectUnsanitizedDoc<RawRule>): doc is SavedObjectUnsanitizedDoc<RawRule> => true,
|
||||
pipeMigrations(
|
||||
addThreatIndicatorPathToThreatMatchRules,
|
||||
addRACRuleTypes,
|
||||
|
@ -149,10 +149,10 @@ export function getMigrations(
|
|||
}
|
||||
|
||||
function executeMigrationWithErrorHandling(
|
||||
migrationFunc: SavedObjectMigrationFn<RawAlert, RawAlert>,
|
||||
migrationFunc: SavedObjectMigrationFn<RawRule, RawRule>,
|
||||
version: string
|
||||
) {
|
||||
return (doc: SavedObjectUnsanitizedDoc<RawAlert>, context: SavedObjectMigrationContext) => {
|
||||
return (doc: SavedObjectUnsanitizedDoc<RawRule>, context: SavedObjectMigrationContext) => {
|
||||
try {
|
||||
return migrationFunc(doc, context);
|
||||
} catch (ex) {
|
||||
|
@ -170,8 +170,8 @@ function executeMigrationWithErrorHandling(
|
|||
}
|
||||
|
||||
const setAlertUpdatedAtDate = (
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> => {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> => {
|
||||
const updatedAt = doc.updated_at || doc.attributes.createdAt;
|
||||
return {
|
||||
...doc,
|
||||
|
@ -183,8 +183,8 @@ const setAlertUpdatedAtDate = (
|
|||
};
|
||||
|
||||
const setNotifyWhen = (
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> => {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> => {
|
||||
const notifyWhen = doc.attributes.throttle ? 'onThrottleInterval' : 'onActiveAlert';
|
||||
return {
|
||||
...doc,
|
||||
|
@ -204,8 +204,8 @@ const consumersToChange: Map<string, string> = new Map(
|
|||
);
|
||||
|
||||
function markAsLegacyAndChangeConsumer(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const {
|
||||
attributes: { consumer },
|
||||
} = doc;
|
||||
|
@ -223,8 +223,8 @@ function markAsLegacyAndChangeConsumer(
|
|||
}
|
||||
|
||||
function setAlertIdAsDefaultDedupkeyOnPagerDutyActions(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const { attributes } = doc;
|
||||
return {
|
||||
...doc,
|
||||
|
@ -251,8 +251,8 @@ function setAlertIdAsDefaultDedupkeyOnPagerDutyActions(
|
|||
}
|
||||
|
||||
function initializeExecutionStatus(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const { attributes } = doc;
|
||||
return {
|
||||
...doc,
|
||||
|
@ -277,8 +277,8 @@ function isEmptyObject(obj: {}) {
|
|||
}
|
||||
|
||||
function restructureConnectorsThatSupportIncident(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const { actions } = doc.attributes;
|
||||
const newActions = actions.reduce((acc, action) => {
|
||||
if (
|
||||
|
@ -416,8 +416,8 @@ function convertNullToUndefined(attribute: SavedObjectAttribute) {
|
|||
}
|
||||
|
||||
function removeNullsFromSecurityRules(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const {
|
||||
attributes: { params },
|
||||
} = doc;
|
||||
|
@ -490,8 +490,8 @@ function removeNullsFromSecurityRules(
|
|||
* @returns The document with the author field fleshed in.
|
||||
*/
|
||||
function removeNullAuthorFromSecurityRules(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const {
|
||||
attributes: { params },
|
||||
} = doc;
|
||||
|
@ -519,8 +519,8 @@ function removeNullAuthorFromSecurityRules(
|
|||
* @returns The document migrated with saved object references
|
||||
*/
|
||||
function addExceptionListsToReferences(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const {
|
||||
attributes: {
|
||||
params: { exceptionsList },
|
||||
|
@ -610,8 +610,8 @@ function removeMalformedExceptionsList(
|
|||
* @returns The document migrated with saved object references
|
||||
*/
|
||||
function addRuleIdsToLegacyNotificationReferences(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const {
|
||||
attributes: {
|
||||
params: { ruleAlertId },
|
||||
|
@ -641,9 +641,7 @@ function addRuleIdsToLegacyNotificationReferences(
|
|||
}
|
||||
}
|
||||
|
||||
function setLegacyId(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
function setLegacyId(doc: SavedObjectUnsanitizedDoc<RawRule>): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const { id } = doc;
|
||||
return {
|
||||
...doc,
|
||||
|
@ -655,8 +653,8 @@ function setLegacyId(
|
|||
}
|
||||
|
||||
function addRACRuleTypes(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const ruleType = doc.attributes.params.type;
|
||||
return isSiemSignalsRuleType(doc) && isRuleType(ruleType)
|
||||
? {
|
||||
|
@ -674,8 +672,8 @@ function addRACRuleTypes(
|
|||
}
|
||||
|
||||
function addThreatIndicatorPathToThreatMatchRules(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
return isSiemSignalsRuleType(doc) &&
|
||||
doc.attributes.params?.type === 'threat_match' &&
|
||||
!doc.attributes.params.threatIndicatorPath
|
||||
|
@ -695,15 +693,15 @@ function addThreatIndicatorPathToThreatMatchRules(
|
|||
function getRemovePreconfiguredConnectorsFromReferencesFn(
|
||||
isPreconfigured: (connectorId: string) => boolean
|
||||
) {
|
||||
return (doc: SavedObjectUnsanitizedDoc<RawAlert>) => {
|
||||
return (doc: SavedObjectUnsanitizedDoc<RawRule>) => {
|
||||
return removePreconfiguredConnectorsFromReferences(doc, isPreconfigured);
|
||||
};
|
||||
}
|
||||
|
||||
function removePreconfiguredConnectorsFromReferences(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>,
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>,
|
||||
isPreconfigured: (connectorId: string) => boolean
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const {
|
||||
attributes: { actions },
|
||||
references,
|
||||
|
@ -719,7 +717,7 @@ function removePreconfiguredConnectorsFromReferences(
|
|||
);
|
||||
|
||||
const updatedConnectorReferences: SavedObjectReference[] = [];
|
||||
const updatedActions: RawAlert['actions'] = [];
|
||||
const updatedActions: RawRule['actions'] = [];
|
||||
|
||||
// For each connector reference, check if connector is preconfigured
|
||||
// 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
|
||||
// group for actions incorrectly spelt as metrics.invenotry_threshold.fired vs metrics.inventory_threshold.fired
|
||||
function fixInventoryThresholdGroupId(
|
||||
doc: SavedObjectUnsanitizedDoc<RawAlert>
|
||||
): SavedObjectUnsanitizedDoc<RawAlert> {
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
if (doc.attributes.alertTypeId === 'metrics.alert.inventory.threshold') {
|
||||
const {
|
||||
attributes: { actions },
|
||||
|
@ -805,6 +803,6 @@ function getCorrespondingAction(
|
|||
}
|
||||
|
||||
function pipeMigrations(...migrations: AlertMigration[]): AlertMigration {
|
||||
return (doc: SavedObjectUnsanitizedDoc<RawAlert>) =>
|
||||
return (doc: SavedObjectUnsanitizedDoc<RawRule>) =>
|
||||
migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { pick } from 'lodash';
|
||||
import { RawAlert } from '../types';
|
||||
import { RawRule } from '../types';
|
||||
|
||||
import {
|
||||
SavedObjectsClient,
|
||||
|
@ -17,7 +17,7 @@ import {
|
|||
import { AlertAttributesExcludedFromAAD, AlertAttributesExcludedFromAADType } from './index';
|
||||
|
||||
export type PartiallyUpdateableAlertAttributes = Partial<
|
||||
Pick<RawAlert, AlertAttributesExcludedFromAADType>
|
||||
Pick<RawRule, AlertAttributesExcludedFromAADType>
|
||||
>;
|
||||
|
||||
export interface PartiallyUpdateAlertSavedObjectOptions {
|
||||
|
@ -40,7 +40,7 @@ export async function partiallyUpdateAlert(
|
|||
): Promise<void> {
|
||||
// ensure we only have the valid attributes excluded from AAD
|
||||
const attributeUpdates = pick(attributes, AlertAttributesExcludedFromAAD);
|
||||
const updateOptions: SavedObjectsUpdateOptions<RawAlert> = pick(
|
||||
const updateOptions: SavedObjectsUpdateOptions<RawRule> = pick(
|
||||
options,
|
||||
'namespace',
|
||||
'version',
|
||||
|
@ -48,7 +48,7 @@ export async function partiallyUpdateAlert(
|
|||
);
|
||||
|
||||
try {
|
||||
await savedObjectsClient.update<RawAlert>('alert', id, attributeUpdates, updateOptions);
|
||||
await savedObjectsClient.update<RawRule>('alert', id, attributeUpdates, updateOptions);
|
||||
} catch (err) {
|
||||
if (options?.ignore404 && SavedObjectsErrorHelpers.isNotFoundError(err)) {
|
||||
return;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
*/
|
||||
|
||||
import { transformRulesForExport } from './transform_rule_for_export';
|
||||
jest.mock('../lib/alert_execution_status', () => ({
|
||||
getAlertExecutionStatusPending: () => ({
|
||||
jest.mock('../lib/rule_execution_status', () => ({
|
||||
getRuleExecutionStatusPending: () => ({
|
||||
status: 'pending',
|
||||
lastExecutionDate: '2020-08-20T19:23:38Z',
|
||||
error: null,
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
*/
|
||||
|
||||
import { SavedObject } from 'kibana/server';
|
||||
import { getAlertExecutionStatusPending } from '../lib/alert_execution_status';
|
||||
import { RawAlert } from '../types';
|
||||
import { getRuleExecutionStatusPending } from '../lib/rule_execution_status';
|
||||
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();
|
||||
return rules.map((rule) => transformRuleForExport(rule as SavedObject<RawAlert>, exportDate));
|
||||
return rules.map((rule) => transformRuleForExport(rule as SavedObject<RawRule>, exportDate));
|
||||
}
|
||||
|
||||
function transformRuleForExport(
|
||||
rule: SavedObject<RawAlert>,
|
||||
rule: SavedObject<RawRule>,
|
||||
exportDate: string
|
||||
): SavedObject<RawAlert> {
|
||||
): SavedObject<RawRule> {
|
||||
return {
|
||||
...rule,
|
||||
attributes: {
|
||||
|
@ -27,7 +27,7 @@ function transformRuleForExport(
|
|||
apiKey: null,
|
||||
apiKeyOwner: null,
|
||||
scheduledTaskId: null,
|
||||
executionStatus: getAlertExecutionStatusPending(exportDate),
|
||||
executionStatus: getRuleExecutionStatusPending(exportDate),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,16 +11,16 @@ import { fold } from 'fp-ts/lib/Either';
|
|||
import { ConcreteTaskInstance } from '../../../task_manager/server';
|
||||
import {
|
||||
SanitizedAlert,
|
||||
AlertTaskState,
|
||||
alertParamsSchema,
|
||||
alertStateSchema,
|
||||
AlertTaskParams,
|
||||
RuleTaskState,
|
||||
ruleParamsSchema,
|
||||
ruleStateSchema,
|
||||
RuleTaskParams,
|
||||
AlertTypeParams,
|
||||
} from '../../common';
|
||||
|
||||
export interface AlertTaskInstance extends ConcreteTaskInstance {
|
||||
state: AlertTaskState;
|
||||
params: AlertTaskParams;
|
||||
state: RuleTaskState;
|
||||
params: RuleTaskParams;
|
||||
}
|
||||
|
||||
const enumerateErrorFields = (e: t.Errors) =>
|
||||
|
@ -33,7 +33,7 @@ export function taskInstanceToAlertTaskInstance<Params extends AlertTypeParams>(
|
|||
return {
|
||||
...taskInstance,
|
||||
params: pipe(
|
||||
alertParamsSchema.decode(taskInstance.params),
|
||||
ruleParamsSchema.decode(taskInstance.params),
|
||||
fold((e: t.Errors) => {
|
||||
throw new Error(
|
||||
`Task "${taskInstance.id}" ${
|
||||
|
@ -43,7 +43,7 @@ export function taskInstanceToAlertTaskInstance<Params extends AlertTypeParams>(
|
|||
}, t.identity)
|
||||
),
|
||||
state: pipe(
|
||||
alertStateSchema.decode(taskInstance.state),
|
||||
ruleStateSchema.decode(taskInstance.state),
|
||||
fold((e: t.Errors) => {
|
||||
throw new Error(
|
||||
`Task "${taskInstance.id}" ${
|
||||
|
|
|
@ -16,7 +16,7 @@ import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';
|
|||
import { KibanaRequest } from 'kibana/server';
|
||||
import { asSavedObjectExecutionSource } from '../../../actions/server';
|
||||
import { InjectActionParamsOpts } from './inject_action_params';
|
||||
import { NormalizedAlertType } from '../rule_type_registry';
|
||||
import { NormalizedRuleType } from '../rule_type_registry';
|
||||
import {
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
|
@ -28,7 +28,7 @@ jest.mock('./inject_action_params', () => ({
|
|||
injectActionParams: jest.fn(),
|
||||
}));
|
||||
|
||||
const alertType: NormalizedAlertType<
|
||||
const ruleType: NormalizedRuleType<
|
||||
AlertTypeParams,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
|
@ -71,12 +71,12 @@ const createExecutionHandlerParams: jest.Mocked<
|
|||
> = {
|
||||
actionsPlugin: mockActionsPlugin,
|
||||
spaceId: 'test1',
|
||||
alertId: '1',
|
||||
alertName: 'name-of-alert',
|
||||
ruleId: '1',
|
||||
ruleName: 'name-of-alert',
|
||||
tags: ['tag-A', 'tag-B'],
|
||||
apiKey: 'MTIzOmFiYw==',
|
||||
kibanaBaseUrl: 'http://localhost:5601',
|
||||
alertType,
|
||||
ruleType,
|
||||
logger: loggingSystemMock.create().get(),
|
||||
eventLogger: mockEventLogger,
|
||||
actions: [
|
||||
|
@ -93,13 +93,13 @@ const createExecutionHandlerParams: jest.Mocked<
|
|||
},
|
||||
],
|
||||
request: {} as KibanaRequest,
|
||||
alertParams: {
|
||||
ruleParams: {
|
||||
foo: true,
|
||||
contextVal: 'My other {{context.value}} goes here',
|
||||
stateVal: 'My other {{state.value}} goes here',
|
||||
},
|
||||
supportsEphemeralTasks: false,
|
||||
maxEphemeralActionsPerAlert: 10,
|
||||
maxEphemeralActionsPerRule: 10,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -123,7 +123,7 @@ test('enqueues execution per selected action', async () => {
|
|||
actionGroup: 'default',
|
||||
state: {},
|
||||
context: {},
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
expect(mockActionsPlugin.getActionsClientWithRequest).toHaveBeenCalledWith(
|
||||
createExecutionHandlerParams.request
|
||||
|
@ -244,7 +244,7 @@ test(`doesn't call actionsPlugin.execute for disabled actionTypes`, async () =>
|
|||
actionGroup: 'default',
|
||||
state: {},
|
||||
context: {},
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
|
||||
expect(actionsClient.enqueueExecution).toHaveBeenCalledWith({
|
||||
|
@ -296,7 +296,7 @@ test('trow error error message when action type is disabled', async () => {
|
|||
actionGroup: 'default',
|
||||
state: {},
|
||||
context: {},
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
|
||||
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(0);
|
||||
|
@ -310,7 +310,7 @@ test('trow error error message when action type is disabled', async () => {
|
|||
actionGroup: 'default',
|
||||
state: {},
|
||||
context: {},
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
@ -321,7 +321,7 @@ test('limits actionsPlugin.execute per action group', async () => {
|
|||
actionGroup: 'other-group',
|
||||
state: {},
|
||||
context: {},
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
expect(actionsClient.enqueueExecution).not.toHaveBeenCalled();
|
||||
});
|
||||
|
@ -332,7 +332,7 @@ test('context attribute gets parameterized', async () => {
|
|||
actionGroup: 'default',
|
||||
context: { value: 'context-val' },
|
||||
state: {},
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
|
||||
expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
|
@ -373,7 +373,7 @@ test('state attribute gets parameterized', async () => {
|
|||
actionGroup: 'default',
|
||||
context: {},
|
||||
state: { value: 'state-val' },
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1);
|
||||
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 result = await executionHandler({
|
||||
// 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',
|
||||
context: {},
|
||||
state: {},
|
||||
alertInstanceId: '2',
|
||||
alertId: '2',
|
||||
});
|
||||
expect(result).toBeUndefined();
|
||||
expect(createExecutionHandlerParams.logger.error).toHaveBeenCalledWith(
|
||||
'Invalid action group "invalid-group" for alert "test".'
|
||||
'Invalid action group "invalid-group" for rule "test".'
|
||||
);
|
||||
});
|
||||
|
|
|
@ -19,9 +19,9 @@ import {
|
|||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
RawAlert,
|
||||
RawRule,
|
||||
} from '../types';
|
||||
import { NormalizedAlertType, UntypedNormalizedAlertType } from '../rule_type_registry';
|
||||
import { NormalizedRuleType, UntypedNormalizedRuleType } from '../rule_type_registry';
|
||||
import { isEphemeralTaskRejectedDueToCapacityError } from '../../../task_manager/server';
|
||||
import { createAlertEventLogRecordObject } from '../lib/create_alert_event_log_record_object';
|
||||
|
||||
|
@ -34,15 +34,15 @@ export interface CreateExecutionHandlerOptions<
|
|||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
> {
|
||||
alertId: string;
|
||||
alertName: string;
|
||||
ruleId: string;
|
||||
ruleName: string;
|
||||
tags?: string[];
|
||||
actionsPlugin: ActionsPluginStartContract;
|
||||
actions: AlertAction[];
|
||||
spaceId: string;
|
||||
apiKey: RawAlert['apiKey'];
|
||||
apiKey: RawRule['apiKey'];
|
||||
kibanaBaseUrl: string | undefined;
|
||||
alertType: NormalizedAlertType<
|
||||
ruleType: NormalizedRuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -54,15 +54,15 @@ export interface CreateExecutionHandlerOptions<
|
|||
logger: Logger;
|
||||
eventLogger: IEventLogger;
|
||||
request: KibanaRequest;
|
||||
alertParams: AlertTypeParams;
|
||||
ruleParams: AlertTypeParams;
|
||||
supportsEphemeralTasks: boolean;
|
||||
maxEphemeralActionsPerAlert: number;
|
||||
maxEphemeralActionsPerRule: number;
|
||||
}
|
||||
|
||||
interface ExecutionHandlerOptions<ActionGroupIds extends string> {
|
||||
actionGroup: ActionGroupIds;
|
||||
actionSubgroup?: string;
|
||||
alertInstanceId: string;
|
||||
alertId: string;
|
||||
context: AlertInstanceContext;
|
||||
state: AlertInstanceState;
|
||||
}
|
||||
|
@ -81,20 +81,20 @@ export function createExecutionHandler<
|
|||
RecoveryActionGroupId extends string
|
||||
>({
|
||||
logger,
|
||||
alertId,
|
||||
alertName,
|
||||
ruleId,
|
||||
ruleName,
|
||||
tags,
|
||||
actionsPlugin,
|
||||
actions: alertActions,
|
||||
actions: ruleActions,
|
||||
spaceId,
|
||||
apiKey,
|
||||
alertType,
|
||||
ruleType,
|
||||
kibanaBaseUrl,
|
||||
eventLogger,
|
||||
request,
|
||||
alertParams,
|
||||
ruleParams,
|
||||
supportsEphemeralTasks,
|
||||
maxEphemeralActionsPerAlert,
|
||||
maxEphemeralActionsPerRule,
|
||||
}: CreateExecutionHandlerOptions<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
|
@ -104,66 +104,66 @@ export function createExecutionHandler<
|
|||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>): ExecutionHandler<ActionGroupIds | RecoveryActionGroupId> {
|
||||
const alertTypeActionGroups = new Map(
|
||||
alertType.actionGroups.map((actionGroup) => [actionGroup.id, actionGroup.name])
|
||||
const ruleTypeActionGroups = new Map(
|
||||
ruleType.actionGroups.map((actionGroup) => [actionGroup.id, actionGroup.name])
|
||||
);
|
||||
return async ({
|
||||
actionGroup,
|
||||
actionSubgroup,
|
||||
context,
|
||||
state,
|
||||
alertInstanceId,
|
||||
alertId,
|
||||
}: ExecutionHandlerOptions<ActionGroupIds | RecoveryActionGroupId>) => {
|
||||
if (!alertTypeActionGroups.has(actionGroup)) {
|
||||
logger.error(`Invalid action group "${actionGroup}" for alert "${alertType.id}".`);
|
||||
if (!ruleTypeActionGroups.has(actionGroup)) {
|
||||
logger.error(`Invalid action group "${actionGroup}" for rule "${ruleType.id}".`);
|
||||
return;
|
||||
}
|
||||
const actions = alertActions
|
||||
const actions = ruleActions
|
||||
.filter(({ group }) => group === actionGroup)
|
||||
.map((action) => {
|
||||
return {
|
||||
...action,
|
||||
params: transformActionParams({
|
||||
actionsPlugin,
|
||||
alertId,
|
||||
alertType: alertType.id,
|
||||
alertId: ruleId,
|
||||
alertType: ruleType.id,
|
||||
actionTypeId: action.actionTypeId,
|
||||
alertName,
|
||||
alertName: ruleName,
|
||||
spaceId,
|
||||
tags,
|
||||
alertInstanceId,
|
||||
alertInstanceId: alertId,
|
||||
alertActionGroup: actionGroup,
|
||||
alertActionGroupName: alertTypeActionGroups.get(actionGroup)!,
|
||||
alertActionGroupName: ruleTypeActionGroups.get(actionGroup)!,
|
||||
alertActionSubgroup: actionSubgroup,
|
||||
context,
|
||||
actionParams: action.params,
|
||||
actionId: action.id,
|
||||
state,
|
||||
kibanaBaseUrl,
|
||||
alertParams,
|
||||
alertParams: ruleParams,
|
||||
}),
|
||||
};
|
||||
})
|
||||
.map((action) => ({
|
||||
...action,
|
||||
params: injectActionParams({
|
||||
ruleId: alertId,
|
||||
ruleId,
|
||||
spaceId,
|
||||
actionParams: action.params,
|
||||
actionTypeId: action.actionTypeId,
|
||||
}),
|
||||
}));
|
||||
|
||||
const alertLabel = `${alertType.id}:${alertId}: '${alertName}'`;
|
||||
const ruleLabel = `${ruleType.id}:${ruleId}: '${ruleName}'`;
|
||||
|
||||
const actionsClient = await actionsPlugin.getActionsClientWithRequest(request);
|
||||
let ephemeralActionsToSchedule = maxEphemeralActionsPerAlert;
|
||||
let ephemeralActionsToSchedule = maxEphemeralActionsPerRule;
|
||||
for (const action of actions) {
|
||||
if (
|
||||
!actionsPlugin.isActionExecutable(action.id, action.actionTypeId, { notifyUsage: true })
|
||||
) {
|
||||
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;
|
||||
}
|
||||
|
@ -176,15 +176,15 @@ export function createExecutionHandler<
|
|||
spaceId,
|
||||
apiKey: apiKey ?? null,
|
||||
source: asSavedObjectExecutionSource({
|
||||
id: alertId,
|
||||
id: ruleId,
|
||||
type: 'alert',
|
||||
}),
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: alertId,
|
||||
id: ruleId,
|
||||
type: 'alert',
|
||||
namespace: namespace.namespace,
|
||||
typeId: alertType.id,
|
||||
typeId: ruleType.id,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -203,18 +203,18 @@ export function createExecutionHandler<
|
|||
}
|
||||
|
||||
const event = createAlertEventLogRecordObject({
|
||||
ruleId: alertId,
|
||||
ruleType: alertType as UntypedNormalizedAlertType,
|
||||
ruleId,
|
||||
ruleType: ruleType as UntypedNormalizedRuleType,
|
||||
action: EVENT_LOG_ACTIONS.executeAction,
|
||||
instanceId: alertInstanceId,
|
||||
instanceId: alertId,
|
||||
group: actionGroup,
|
||||
subgroup: actionSubgroup,
|
||||
ruleName: alertName,
|
||||
ruleName,
|
||||
savedObjects: [
|
||||
{
|
||||
type: 'alert',
|
||||
id: alertId,
|
||||
typeId: alertType.id,
|
||||
id: ruleId,
|
||||
typeId: ruleType.id,
|
||||
relation: SAVED_OBJECT_REL_PRIMARY,
|
||||
},
|
||||
{
|
||||
|
@ -224,7 +224,7 @@ export function createExecutionHandler<
|
|||
},
|
||||
],
|
||||
...namespace,
|
||||
message: `alert: ${alertLabel} instanceId: '${alertInstanceId}' scheduled ${
|
||||
message: `alert: ${ruleLabel} instanceId: '${alertId}' scheduled ${
|
||||
actionSubgroup
|
||||
? `actionGroup(subgroup): '${actionGroup}(${actionSubgroup})'`
|
||||
: `actionGroup: '${actionGroup}'`
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -29,10 +29,10 @@ import { alertsMock, rulesClientMock } from '../mocks';
|
|||
import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';
|
||||
import { IEventLogger } from '../../../event_log/server';
|
||||
import { Alert, RecoveredActionGroup } from '../../common';
|
||||
import { UntypedNormalizedAlertType } from '../rule_type_registry';
|
||||
import { UntypedNormalizedRuleType } from '../rule_type_registry';
|
||||
import { ruleTypeRegistryMock } from '../rule_type_registry.mock';
|
||||
|
||||
const ruleType: jest.Mocked<UntypedNormalizedAlertType> = {
|
||||
const ruleType: jest.Mocked<UntypedNormalizedRuleType> = {
|
||||
id: 'test',
|
||||
name: 'My test rule',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }, RecoveredActionGroup],
|
||||
|
@ -100,7 +100,7 @@ describe('Task Runner Cancel', () => {
|
|||
ruleTypeRegistry,
|
||||
kibanaBaseUrl: 'https://localhost:5601',
|
||||
supportsEphemeralTasks: false,
|
||||
maxEphemeralActionsPerAlert: 10,
|
||||
maxEphemeralActionsPerRule: 10,
|
||||
cancelAlertsOnRuleTimeout: true,
|
||||
};
|
||||
|
||||
|
@ -215,7 +215,7 @@ describe('Task Runner Cancel', () => {
|
|||
scheduled: '1970-01-01T00:00:00.000Z',
|
||||
},
|
||||
},
|
||||
message: 'alert execution start: "1"',
|
||||
message: 'rule execution start: "1"',
|
||||
rule: {
|
||||
category: 'test',
|
||||
id: '1',
|
||||
|
@ -271,7 +271,7 @@ describe('Task Runner Cancel', () => {
|
|||
scheduled: '1970-01-01T00:00:00.000Z',
|
||||
},
|
||||
},
|
||||
message: `alert executed: test:1: 'rule-name'`,
|
||||
message: `rule executed: test:1: 'rule-name'`,
|
||||
rule: {
|
||||
category: 'test',
|
||||
id: '1',
|
||||
|
@ -395,7 +395,7 @@ describe('Task Runner Cancel', () => {
|
|||
|
||||
const logger = taskRunnerFactoryInitializerParams.logger;
|
||||
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(
|
||||
2,
|
||||
`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(
|
||||
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(
|
||||
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(
|
||||
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;
|
||||
|
@ -440,7 +440,7 @@ describe('Task Runner Cancel', () => {
|
|||
},
|
||||
],
|
||||
},
|
||||
message: `alert execution start: \"1\"`,
|
||||
message: `rule execution start: \"1\"`,
|
||||
rule: {
|
||||
category: 'test',
|
||||
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: {
|
||||
category: 'test',
|
||||
id: '1',
|
||||
|
@ -512,7 +512,7 @@ describe('Task Runner Cancel', () => {
|
|||
function testActionsExecute() {
|
||||
const logger = taskRunnerFactoryInitializerParams.logger;
|
||||
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(
|
||||
2,
|
||||
`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(
|
||||
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(
|
||||
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;
|
||||
|
@ -553,7 +553,7 @@ describe('Task Runner Cancel', () => {
|
|||
},
|
||||
],
|
||||
},
|
||||
message: `alert execution start: "1"`,
|
||||
message: `rule execution start: "1"`,
|
||||
rule: {
|
||||
category: 'test',
|
||||
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: {
|
||||
category: 'test',
|
||||
id: '1',
|
||||
|
@ -636,7 +636,7 @@ describe('Task Runner Cancel', () => {
|
|||
{ 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: {
|
||||
category: 'test',
|
||||
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: {
|
||||
category: 'test',
|
||||
id: '1',
|
||||
|
|
|
@ -17,13 +17,13 @@ import {
|
|||
import { actionsMock } from '../../../actions/server/mocks';
|
||||
import { alertsMock, rulesClientMock } from '../mocks';
|
||||
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 { executionContextServiceMock } from '../../../../../src/core/server/mocks';
|
||||
|
||||
const executionContext = executionContextServiceMock.createSetupContract();
|
||||
|
||||
const alertType: UntypedNormalizedAlertType = {
|
||||
const ruleType: UntypedNormalizedRuleType = {
|
||||
id: 'test',
|
||||
name: 'My test alert',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -83,7 +83,7 @@ describe('Task Runner Factory', () => {
|
|||
ruleTypeRegistry: ruleTypeRegistryMock.create(),
|
||||
kibanaBaseUrl: 'https://localhost:5601',
|
||||
supportsEphemeralTasks: true,
|
||||
maxEphemeralActionsPerAlert: 10,
|
||||
maxEphemeralActionsPerRule: 10,
|
||||
cancelAlertsOnRuleTimeout: true,
|
||||
executionContext,
|
||||
};
|
||||
|
@ -96,7 +96,7 @@ describe('Task Runner Factory', () => {
|
|||
test(`throws an error if factory isn't initialized`, () => {
|
||||
const factory = new TaskRunnerFactory();
|
||||
expect(() =>
|
||||
factory.create(alertType, { taskInstance: mockedTaskInstance })
|
||||
factory.create(ruleType, { taskInstance: mockedTaskInstance })
|
||||
).toThrowErrorMatchingInlineSnapshot(`"TaskRunnerFactory not initialized"`);
|
||||
});
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import {
|
|||
import { TaskRunner } from './task_runner';
|
||||
import { IEventLogger } from '../../../event_log/server';
|
||||
import { RulesClient } from '../rules_client';
|
||||
import { NormalizedAlertType } from '../rule_type_registry';
|
||||
import { NormalizedRuleType } from '../rule_type_registry';
|
||||
|
||||
export interface TaskRunnerContext {
|
||||
logger: Logger;
|
||||
|
@ -44,7 +44,7 @@ export interface TaskRunnerContext {
|
|||
ruleTypeRegistry: RuleTypeRegistry;
|
||||
kibanaBaseUrl: string | undefined;
|
||||
supportsEphemeralTasks: boolean;
|
||||
maxEphemeralActionsPerAlert: number;
|
||||
maxEphemeralActionsPerRule: number;
|
||||
cancelAlertsOnRuleTimeout: boolean;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ export class TaskRunnerFactory {
|
|||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: NormalizedAlertType<
|
||||
ruleType: NormalizedRuleType<
|
||||
Params,
|
||||
ExtractedParams,
|
||||
State,
|
||||
|
@ -92,6 +92,6 @@ export class TaskRunnerFactory {
|
|||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>(alertType, taskInstance, this.taskRunnerContext!);
|
||||
>(ruleType, taskInstance, this.taskRunnerContext!);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ export type ExecutorType<
|
|||
export interface AlertTypeParamsValidator<Params extends AlertTypeParams> {
|
||||
validate: (object: unknown) => Params;
|
||||
}
|
||||
export interface AlertType<
|
||||
export interface RuleType<
|
||||
Params extends AlertTypeParams = never,
|
||||
ExtractedParams extends AlertTypeParams = never,
|
||||
State extends AlertTypeState = never,
|
||||
|
@ -163,7 +163,7 @@ export interface AlertType<
|
|||
ruleTaskTimeout?: string;
|
||||
cancelAlertsOnRuleTimeout?: boolean;
|
||||
}
|
||||
export type UntypedAlertType = AlertType<
|
||||
export type UntypedRuleType = RuleType<
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
|
@ -184,7 +184,7 @@ export interface AlertMeta extends SavedObjectAttributes {
|
|||
// 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
|
||||
// delete any previous error if the current status has no error
|
||||
export interface RawAlertExecutionStatus extends SavedObjectAttributes {
|
||||
export interface RawRuleExecutionStatus extends SavedObjectAttributes {
|
||||
status: AlertExecutionStatuses;
|
||||
lastExecutionDate: string;
|
||||
lastDuration?: number;
|
||||
|
@ -201,7 +201,7 @@ export interface AlertWithLegacyId<Params extends AlertTypeParams = never> exten
|
|||
legacyId: string | null;
|
||||
}
|
||||
|
||||
export type SanitizedAlertWithLegacyId<Params extends AlertTypeParams = never> = Omit<
|
||||
export type SanitizedRuleWithLegacyId<Params extends AlertTypeParams = never> = Omit<
|
||||
AlertWithLegacyId<Params>,
|
||||
'apiKey'
|
||||
>;
|
||||
|
@ -212,11 +212,11 @@ export type PartialAlertWithLegacyId<Params extends AlertTypeParams = never> = P
|
|||
> &
|
||||
Partial<Omit<AlertWithLegacyId<Params>, 'id'>>;
|
||||
|
||||
export interface RawAlert extends SavedObjectAttributes {
|
||||
export interface RawRule extends SavedObjectAttributes {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
tags: string[];
|
||||
alertTypeId: string;
|
||||
alertTypeId: string; // this cannot be renamed since it is in the saved object
|
||||
consumer: string;
|
||||
legacyId: string | null;
|
||||
schedule: SavedObjectAttributes;
|
||||
|
@ -234,11 +234,11 @@ export interface RawAlert extends SavedObjectAttributes {
|
|||
muteAll: boolean;
|
||||
mutedInstanceIds: string[];
|
||||
meta?: AlertMeta;
|
||||
executionStatus: RawAlertExecutionStatus;
|
||||
executionStatus: RawRuleExecutionStatus;
|
||||
}
|
||||
|
||||
export type AlertInfoParams = Pick<
|
||||
RawAlert,
|
||||
RawRule,
|
||||
| 'params'
|
||||
| 'throttle'
|
||||
| 'notifyWhen'
|
||||
|
|
|
@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { MlPluginSetup } from '../../../../../ml/server';
|
||||
import {
|
||||
AlertType as RuleType,
|
||||
RuleType,
|
||||
AlertInstanceState as AlertState,
|
||||
AlertInstanceContext as AlertContext,
|
||||
} from '../../../../../alerting/server';
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { schema } from '@kbn/config-schema';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
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 {
|
||||
createMetricThresholdExecutor,
|
||||
|
@ -31,7 +31,7 @@ import {
|
|||
type MetricThresholdAllowedActionGroups = ActionGroupIdsOf<
|
||||
typeof FIRED_ACTIONS | typeof WARNING_ACTIONS
|
||||
>;
|
||||
export type MetricThresholdAlertType = Omit<AlertType, 'ActionGroupIdsOf'> & {
|
||||
export type MetricThresholdAlertType = Omit<RuleType, 'ActionGroupIdsOf'> & {
|
||||
ActionGroupIdsOf: MetricThresholdAllowedActionGroups;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { Logger, ElasticsearchClient } from 'kibana/server';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertExecutorOptions,
|
||||
AlertInstance,
|
||||
RulesClient,
|
||||
|
@ -80,7 +80,7 @@ export class BaseRule {
|
|||
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;
|
||||
return {
|
||||
id,
|
||||
|
|
|
@ -12,14 +12,14 @@ import {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
} 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';
|
||||
|
||||
type SimpleAlertType<
|
||||
TState extends AlertTypeState,
|
||||
TParams extends AlertTypeParams = {},
|
||||
TAlertInstanceContext extends AlertInstanceContext = {}
|
||||
> = AlertType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>;
|
||||
> = RuleType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>;
|
||||
|
||||
export type AlertTypeExecutor<
|
||||
TState extends AlertTypeState,
|
||||
|
@ -38,7 +38,7 @@ export type AlertTypeWithExecutor<
|
|||
TAlertInstanceContext extends AlertInstanceContext = {},
|
||||
TServices extends Record<string, any> = {}
|
||||
> = Omit<
|
||||
AlertType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>,
|
||||
RuleType<TParams, TParams, TState, AlertInstanceState, TAlertInstanceContext, string, string>,
|
||||
'executor'
|
||||
> & {
|
||||
executor: AlertTypeExecutor<TState, TParams, TAlertInstanceContext, TServices>;
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
AlertExecutorOptions,
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
} from '../../../alerting/server';
|
||||
|
@ -39,7 +39,7 @@ export type PersistenceAlertType<
|
|||
TInstanceContext extends AlertInstanceContext = {},
|
||||
TActionGroupIds extends string = never
|
||||
> = Omit<
|
||||
AlertType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>,
|
||||
RuleType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>,
|
||||
'executor'
|
||||
> & {
|
||||
executor: (
|
||||
|
@ -65,4 +65,4 @@ export type CreatePersistenceRuleTypeWrapper = (options: {
|
|||
TActionGroupIds extends string = never
|
||||
>(
|
||||
type: PersistenceAlertType<TParams, TState, TInstanceContext, TActionGroupIds>
|
||||
) => AlertType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>;
|
||||
) => RuleType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>;
|
||||
|
|
|
@ -10,7 +10,7 @@ import { schema, TypeOf } from '@kbn/config-schema';
|
|||
import {
|
||||
RulesClient,
|
||||
PartialAlert,
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
|
@ -103,7 +103,7 @@ export type LegacyNotificationExecutorOptions = AlertExecutorOptions<
|
|||
*/
|
||||
export const legacyIsNotificationAlertExecutor = (
|
||||
obj: LegacyNotificationAlertTypeDefinition
|
||||
): obj is AlertType<
|
||||
): obj is RuleType<
|
||||
LegacyRuleNotificationAlertTypeParams,
|
||||
LegacyRuleNotificationAlertTypeParams,
|
||||
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
|
||||
*/
|
||||
export type LegacyNotificationAlertTypeDefinition = Omit<
|
||||
AlertType<
|
||||
RuleType<
|
||||
LegacyRuleNotificationAlertTypeParams,
|
||||
LegacyRuleNotificationAlertTypeParams,
|
||||
AlertTypeState,
|
||||
|
|
|
@ -11,7 +11,7 @@ import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
|||
import { Logger } from '@kbn/logging';
|
||||
import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
|
||||
import { AlertExecutorOptions, AlertType } from '../../../../../alerting/server';
|
||||
import { AlertExecutorOptions, RuleType } from '../../../../../alerting/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
|
@ -73,7 +73,7 @@ export type SecurityAlertType<
|
|||
TInstanceContext extends AlertInstanceContext = {},
|
||||
TActionGroupIds extends string = never
|
||||
> = Omit<
|
||||
AlertType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>,
|
||||
RuleType<TParams, TParams, TState, AlertInstanceState, TInstanceContext, TActionGroupIds>,
|
||||
'executor'
|
||||
> & {
|
||||
executor: (
|
||||
|
@ -107,7 +107,7 @@ export type CreateSecurityRuleTypeWrapper = (
|
|||
TInstanceContext extends AlertInstanceContext = {}
|
||||
>(
|
||||
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 RACAlert = Exclude<
|
||||
|
|
|
@ -12,7 +12,7 @@ import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-t
|
|||
import { Status } from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema';
|
||||
import {
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
|
@ -196,7 +196,7 @@ export type RuleExecutorOptions = AlertExecutorOptions<
|
|||
// since we are only increasing the strictness of params.
|
||||
export const isAlertExecutor = (
|
||||
obj: SignalRuleAlertTypeDefinition
|
||||
): obj is AlertType<
|
||||
): obj is RuleType<
|
||||
RuleParams,
|
||||
RuleParams, // This type is used for useSavedObjectReferences, use an Omit here if you want to remove any values.
|
||||
AlertTypeState,
|
||||
|
@ -207,7 +207,7 @@ export const isAlertExecutor = (
|
|||
return true;
|
||||
};
|
||||
|
||||
export type SignalRuleAlertTypeDefinition = AlertType<
|
||||
export type SignalRuleAlertTypeDefinition = RuleType<
|
||||
RuleParams,
|
||||
RuleParams, // This type is used for useSavedObjectReferences, use an Omit here if you want to remove any values.
|
||||
AlertTypeState,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { Logger } from 'src/core/server';
|
||||
import { AlertType, AlertExecutorOptions } from '../../types';
|
||||
import { RuleType, AlertExecutorOptions } from '../../types';
|
||||
import { ActionContext, EsQueryAlertActionContext, addMessages } from './action_context';
|
||||
import {
|
||||
EsQueryAlertParams,
|
||||
|
@ -25,7 +25,7 @@ export const ES_QUERY_ID = '.es-query';
|
|||
export const ActionGroupId = 'query matched';
|
||||
export const ConditionMetAlertInstanceId = 'query matched';
|
||||
|
||||
export function getAlertType(logger: Logger): AlertType<
|
||||
export function getAlertType(logger: Logger): RuleType<
|
||||
EsQueryAlertParams,
|
||||
never, // Only use if defining useSavedObjectReferences hook
|
||||
EsQueryAlertState,
|
||||
|
|
|
@ -11,7 +11,7 @@ import { Logger, SavedObjectReference } from 'src/core/server';
|
|||
import { STACK_ALERTS_FEATURE_ID } from '../../../common';
|
||||
import { getGeoContainmentExecutor } from './geo_containment';
|
||||
import {
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
|
@ -147,7 +147,7 @@ export interface GeoContainmentInstanceContext extends AlertInstanceContext {
|
|||
containingBoundaryName: unknown;
|
||||
}
|
||||
|
||||
export type GeoContainmentAlertType = AlertType<
|
||||
export type GeoContainmentAlertType = RuleType<
|
||||
GeoContainmentParams,
|
||||
GeoContainmentExtractedParams,
|
||||
GeoContainmentState,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
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 { ActionContext, BaseActionContext, addMessages } from './action_context';
|
||||
import { STACK_ALERTS_FEATURE_ID } from '../../../common';
|
||||
|
@ -23,7 +23,7 @@ export const ActionGroupId = 'threshold met';
|
|||
export function getAlertType(
|
||||
logger: Logger,
|
||||
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', {
|
||||
defaultMessage: 'Index threshold',
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ import { PluginSetupContract as AlertingSetup } from '../../alerting/server';
|
|||
|
||||
export type {
|
||||
PluginSetupContract as AlertingSetup,
|
||||
AlertType,
|
||||
RuleType,
|
||||
RuleParamsAndRefs,
|
||||
AlertExecutorOptions,
|
||||
} from '../../alerting/server';
|
||||
|
|
|
@ -15,7 +15,7 @@ import type {
|
|||
} from '../../../../../alerting/common';
|
||||
import { PLUGIN, TRANSFORM_RULE_TYPE } from '../../../../common/constants';
|
||||
import { transformHealthRuleParams, TransformHealthRuleParams } from './schema';
|
||||
import { AlertType } from '../../../../../alerting/server';
|
||||
import { RuleType } from '../../../../../alerting/server';
|
||||
import { transformHealthServiceProvider } from './transform_health_service';
|
||||
import type { PluginSetupContract as AlertingSetup } from '../../../../../alerting/server';
|
||||
|
||||
|
@ -57,7 +57,7 @@ export function registerTransformHealthRuleType(params: RegisterParams) {
|
|||
alerting.registerType(getTransformHealthRuleType());
|
||||
}
|
||||
|
||||
export function getTransformHealthRuleType(): AlertType<
|
||||
export function getTransformHealthRuleType(): RuleType<
|
||||
TransformHealthRuleParams,
|
||||
never,
|
||||
AlertTypeState,
|
||||
|
|
|
@ -5343,16 +5343,16 @@
|
|||
"xpack.alerting.rulesClient.invalidDate": "パラメーター{field}の無効な日付:「{dateValue}」",
|
||||
"xpack.alerting.rulesClient.validateActions.invalidGroups": "無効なアクショングループ:{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.duplicateAlertTypeError": "ルールタイプ\"{id}\"はすでに登録されています。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutAlertTypeError": "ルールタイプ\"{id}\"のデフォルト間隔が無効です:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutAlertTypeError": "ルールタイプ\"{id}\"の最低間隔が無効です:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidTimeoutAlertTypeError": "ルールタイプ\"{id}\"のタイムアウトが無効です:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.duplicateRuleTypeError": "ルールタイプ\"{id}\"はすでに登録されています。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutRuleTypeError": "ルールタイプ\"{id}\"のデフォルト間隔が無効です:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutRuleTypeError": "ルールタイプ\"{id}\"の最低間隔が無効です:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidTimeoutRuleTypeError": "ルールタイプ\"{id}\"のタイムアウトが無効です:{errorMessage}。",
|
||||
"xpack.alerting.savedObjects.goToRulesButtonText": "ルールに移動",
|
||||
"xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "{licenseType} ライセンスの期限が切れたのでアラートタイプ {alertTypeId} は無効です。",
|
||||
"xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "アラート{alertTypeId}は無効です。{licenseType}ライセンスが必要です。アップグレードオプションを表示するには、[ライセンス管理]に移動してください。",
|
||||
"xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "現時点でライセンス情報を入手できないため、アラートタイプ {alertTypeId} は無効です。",
|
||||
"xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "{licenseType} ライセンスの期限が切れたのでアラートタイプ {ruleTypeId} は無効です。",
|
||||
"xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "アラート{ruleTypeId}は無効です。{licenseType}ライセンスが必要です。アップグレードオプションを表示するには、[ライセンス管理]に移動してください。",
|
||||
"xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "現時点でライセンス情報を入手できないため、アラートタイプ {ruleTypeId} は無効です。",
|
||||
"xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "アラートを利用できません。現在ライセンス情報が利用できません。",
|
||||
"xpack.apm.a.thresholdMet": "しきい値一致",
|
||||
"xpack.apm.addDataButtonLabel": "データの追加",
|
||||
|
|
|
@ -5378,18 +5378,18 @@
|
|||
"xpack.alerting.rulesClient.invalidDate": "参数 {field} 的日期无效:“{dateValue}”",
|
||||
"xpack.alerting.rulesClient.validateActions.invalidGroups": "无效操作组:{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.duplicateAlertTypeError": "已注册规则类型“{id}”。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutAlertTypeError": "规则类型“{id}”的默认时间间隔无效:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutAlertTypeError": "规则类型“{id}”的最小时间间隔无效:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidTimeoutAlertTypeError": "规则类型“{id}”的超时无效:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.duplicateRuleTypeError": "已注册规则类型“{id}”。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidDefaultTimeoutRuleTypeError": "规则类型“{id}”的默认时间间隔无效:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidMinimumTimeoutRuleTypeError": "规则类型“{id}”的最小时间间隔无效:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.invalidTimeoutRuleTypeError": "规则类型“{id}”的超时无效:{errorMessage}。",
|
||||
"xpack.alerting.ruleTypeRegistry.register.reservedActionGroupUsageError": "无法注册规则类型 [id=\"{id}\"]。操作组 [{actionGroups}] 由框架保留。",
|
||||
"xpack.alerting.savedObjects.goToRulesButtonText": "前往规则",
|
||||
"xpack.alerting.savedObjects.onImportText": "导入后必须启用 {rulesSavedObjectsLength} 个{rulesSavedObjectsLength, plural,other {规则}}。",
|
||||
"xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "告警类型 {alertTypeId} 已禁用,因为您的{licenseType}许可证已过期。",
|
||||
"xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "告警 {alertTypeId} 已禁用,因为它需要{licenseType}许可证。前往“许可证管理”以查看升级选项。",
|
||||
"xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "告警类型 {alertTypeId} 已禁用,因为许可证信息当前不可用。",
|
||||
"xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "告警类型 {ruleTypeId} 已禁用,因为您的{licenseType}许可证已过期。",
|
||||
"xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "告警 {ruleTypeId} 已禁用,因为它需要{licenseType}许可证。前往“许可证管理”以查看升级选项。",
|
||||
"xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "告警类型 {ruleTypeId} 已禁用,因为许可证信息当前不可用。",
|
||||
"xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "告警不可用 - 许可信息当前不可用。",
|
||||
"xpack.apm.a.thresholdMet": "已达到阈值",
|
||||
"xpack.apm.addDataButtonLabel": "添加数据",
|
||||
|
|
|
@ -8,12 +8,12 @@ import { HttpSetup } from 'kibana/public';
|
|||
import { pipe } from 'fp-ts/lib/pipeable';
|
||||
import { fold } from 'fp-ts/lib/Either';
|
||||
import { Errors, identity } from 'io-ts';
|
||||
import { AlertTaskState } from '../../../types';
|
||||
import { RuleTaskState } from '../../../types';
|
||||
import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants';
|
||||
import { alertStateSchema } from '../../../../../alerting/common';
|
||||
import { ruleStateSchema } from '../../../../../alerting/common';
|
||||
import { AsApiContract, RewriteRequestCase } from '../../../../../actions/common';
|
||||
|
||||
const rewriteBodyRes: RewriteRequestCase<AlertTaskState> = ({
|
||||
const rewriteBodyRes: RewriteRequestCase<RuleTaskState> = ({
|
||||
rule_type_state: alertTypeState,
|
||||
alerts: alertInstances,
|
||||
previous_started_at: previousStartedAt,
|
||||
|
@ -32,17 +32,17 @@ export async function loadAlertState({
|
|||
}: {
|
||||
http: HttpSetup;
|
||||
alertId: string;
|
||||
}): Promise<AlertTaskState> {
|
||||
}): Promise<RuleTaskState> {
|
||||
return await http
|
||||
.get<AsApiContract<AlertTaskState> | EmptyHttpResponse>(
|
||||
.get<AsApiContract<RuleTaskState> | EmptyHttpResponse>(
|
||||
`${INTERNAL_BASE_ALERTING_API_PATH}/rule/${alertId}/state`
|
||||
)
|
||||
.then((state) => (state ? rewriteBodyRes(state) : {}))
|
||||
.then((state: AlertTaskState) => {
|
||||
.then((state: RuleTaskState) => {
|
||||
return pipe(
|
||||
alertStateSchema.decode(state),
|
||||
ruleStateSchema.decode(state),
|
||||
fold((e: Errors) => {
|
||||
throw new Error(`Alert "${alertId}" has invalid state`);
|
||||
throw new Error(`Rule "${alertId}" has invalid state`);
|
||||
}, identity)
|
||||
);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ import React from 'react';
|
|||
import {
|
||||
Alert,
|
||||
AlertType,
|
||||
AlertTaskState,
|
||||
RuleTaskState,
|
||||
AlertSummary,
|
||||
AlertingFrameworkHealth,
|
||||
ResolvedRule,
|
||||
|
@ -56,7 +56,7 @@ export interface ComponentOpts {
|
|||
errors: string[];
|
||||
}>;
|
||||
loadAlert: (id: Alert['id']) => Promise<Alert>;
|
||||
loadAlertState: (id: Alert['id']) => Promise<AlertTaskState>;
|
||||
loadAlertState: (id: Alert['id']) => Promise<RuleTaskState>;
|
||||
loadAlertSummary: (id: Alert['id']) => Promise<AlertSummary>;
|
||||
loadAlertTypes: () => Promise<AlertType[]>;
|
||||
getHealth: () => Promise<AlertingFrameworkHealth>;
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
ResolvedSanitizedRule,
|
||||
AlertAction,
|
||||
AlertAggregations,
|
||||
AlertTaskState,
|
||||
RuleTaskState,
|
||||
AlertSummary,
|
||||
ExecutionDuration,
|
||||
AlertStatus,
|
||||
|
@ -36,7 +36,7 @@ import {
|
|||
AlertNotifyWhenType,
|
||||
AlertTypeParams,
|
||||
ActionVariable,
|
||||
AlertType as CommonAlertType,
|
||||
RuleType as CommonRuleType,
|
||||
} from '../../alerting/common';
|
||||
|
||||
// In Triggers and Actions we treat all `Alert`s as `SanitizedAlert<AlertTypeParams>`
|
||||
|
@ -48,7 +48,7 @@ export type {
|
|||
Alert,
|
||||
AlertAction,
|
||||
AlertAggregations,
|
||||
AlertTaskState,
|
||||
RuleTaskState,
|
||||
AlertSummary,
|
||||
ExecutionDuration,
|
||||
AlertStatus,
|
||||
|
@ -208,7 +208,7 @@ export interface AlertType<
|
|||
ActionGroupIds extends string = string,
|
||||
RecoveryActionGroupId extends string = string
|
||||
> extends Pick<
|
||||
CommonAlertType<ActionGroupIds, RecoveryActionGroupId>,
|
||||
CommonRuleType<ActionGroupIds, RecoveryActionGroupId>,
|
||||
| 'id'
|
||||
| 'name'
|
||||
| 'actionGroups'
|
||||
|
|
|
@ -22,7 +22,7 @@ export default function emailTest({ getService }: FtrProviderContext) {
|
|||
statusCode: 403,
|
||||
error: 'Forbidden',
|
||||
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.',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ import { curry, times } from 'lodash';
|
|||
import { ES_TEST_INDEX_NAME } from '../../../../lib';
|
||||
import { FixtureStartDeps, FixtureSetupDeps } from './plugin';
|
||||
import {
|
||||
AlertType,
|
||||
RuleType,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
AlertTypeState,
|
||||
|
@ -62,7 +62,7 @@ function getAlwaysFiringAlertType() {
|
|||
interface InstanceContext extends AlertInstanceContext {
|
||||
instanceContextValue: boolean;
|
||||
}
|
||||
const result: AlertType<
|
||||
const result: RuleType<
|
||||
ParamsType & AlertTypeParams,
|
||||
never, // Only use if defining useSavedObjectReferences hook
|
||||
State,
|
||||
|
@ -159,7 +159,7 @@ function getCumulativeFiringAlertType() {
|
|||
interface InstanceState extends AlertInstanceState {
|
||||
instanceStateValue: boolean;
|
||||
}
|
||||
const result: AlertType<{}, {}, State, InstanceState, {}, 'default' | 'other'> = {
|
||||
const result: RuleType<{}, {}, State, InstanceState, {}, 'default' | 'other'> = {
|
||||
id: 'test.cumulative-firing',
|
||||
name: 'Test: Cumulative Firing',
|
||||
actionGroups: [
|
||||
|
@ -200,7 +200,7 @@ function getNeverFiringAlertType() {
|
|||
interface State extends AlertTypeState {
|
||||
globalStateValue: boolean;
|
||||
}
|
||||
const result: AlertType<ParamsType, never, State, {}, {}, 'default'> = {
|
||||
const result: RuleType<ParamsType, never, State, {}, {}, 'default'> = {
|
||||
id: 'test.never-firing',
|
||||
name: 'Test: Never firing',
|
||||
actionGroups: [
|
||||
|
@ -241,7 +241,7 @@ function getFailingAlertType() {
|
|||
reference: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: AlertType<ParamsType, never, {}, {}, {}, 'default'> = {
|
||||
const result: RuleType<ParamsType, never, {}, {}, {}, 'default'> = {
|
||||
id: 'test.failing',
|
||||
name: 'Test: Failing',
|
||||
validate: {
|
||||
|
@ -283,7 +283,7 @@ function getAuthorizationAlertType(core: CoreSetup<FixtureStartDeps>) {
|
|||
reference: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: AlertType<ParamsType, never, {}, {}, {}, 'default'> = {
|
||||
const result: RuleType<ParamsType, never, {}, {}, {}, 'default'> = {
|
||||
id: 'test.authorization',
|
||||
name: 'Test: Authorization',
|
||||
actionGroups: [
|
||||
|
@ -371,7 +371,7 @@ function getValidationAlertType() {
|
|||
param1: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: AlertType<ParamsType, never, {}, {}, {}, 'default'> = {
|
||||
const result: RuleType<ParamsType, never, {}, {}, {}, 'default'> = {
|
||||
id: 'test.validation',
|
||||
name: 'Test: Validation',
|
||||
actionGroups: [
|
||||
|
@ -404,7 +404,7 @@ function getPatternFiringAlertType() {
|
|||
interface State extends AlertTypeState {
|
||||
patternIndex?: number;
|
||||
}
|
||||
const result: AlertType<ParamsType, never, State, {}, {}, 'default'> = {
|
||||
const result: RuleType<ParamsType, never, State, {}, {}, 'default'> = {
|
||||
id: 'test.patternFiring',
|
||||
name: 'Test: Firing on a Pattern',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -473,7 +473,7 @@ function getLongRunningPatternRuleType(cancelAlertsOnRuleTimeout: boolean = true
|
|||
interface State extends AlertTypeState {
|
||||
patternIndex?: number;
|
||||
}
|
||||
const result: AlertType<ParamsType, never, State, {}, {}, 'default'> = {
|
||||
const result: RuleType<ParamsType, never, State, {}, {}, 'default'> = {
|
||||
id: `test.patternLongRunning${
|
||||
cancelAlertsOnRuleTimeout === true ? '.cancelAlertsOnRuleTimeout' : ''
|
||||
}`,
|
||||
|
@ -519,7 +519,7 @@ export function defineAlertTypes(
|
|||
core: CoreSetup<FixtureStartDeps>,
|
||||
{ alerting }: Pick<FixtureSetupDeps, 'alerting'>
|
||||
) {
|
||||
const noopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
const noopAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.noop',
|
||||
name: 'Test: Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -529,7 +529,7 @@ export function defineAlertTypes(
|
|||
isExportable: true,
|
||||
async executor() {},
|
||||
};
|
||||
const goldNoopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
const goldNoopAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.gold.noop',
|
||||
name: 'Test: Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -539,7 +539,7 @@ export function defineAlertTypes(
|
|||
isExportable: true,
|
||||
async executor() {},
|
||||
};
|
||||
const onlyContextVariablesAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
const onlyContextVariablesAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.onlyContextVariables',
|
||||
name: 'Test: Only Context Variables',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -552,7 +552,7 @@ export function defineAlertTypes(
|
|||
},
|
||||
async executor() {},
|
||||
};
|
||||
const onlyStateVariablesAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
const onlyStateVariablesAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.onlyStateVariables',
|
||||
name: 'Test: Only State Variables',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -565,7 +565,7 @@ export function defineAlertTypes(
|
|||
isExportable: true,
|
||||
async executor() {},
|
||||
};
|
||||
const throwAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
const throwAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.throw',
|
||||
name: 'Test: Throw',
|
||||
actionGroups: [
|
||||
|
@ -582,7 +582,7 @@ export function defineAlertTypes(
|
|||
throw new Error('this alert is intended to fail');
|
||||
},
|
||||
};
|
||||
const longRunningAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
const longRunningAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.longRunning',
|
||||
name: 'Test: Long Running',
|
||||
actionGroups: [
|
||||
|
@ -599,21 +599,20 @@ export function defineAlertTypes(
|
|||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
},
|
||||
};
|
||||
const exampleAlwaysFiringAlertType: AlertType<{}, {}, {}, {}, {}, 'small' | 'medium' | 'large'> =
|
||||
{
|
||||
id: 'example.always-firing',
|
||||
name: 'Always firing',
|
||||
actionGroups: [
|
||||
{ id: 'small', name: 'Small t-shirt' },
|
||||
{ id: 'medium', name: 'Medium t-shirt' },
|
||||
{ id: 'large', name: 'Large t-shirt' },
|
||||
],
|
||||
defaultActionGroupId: 'small',
|
||||
minimumLicenseRequired: 'basic',
|
||||
isExportable: true,
|
||||
async executor() {},
|
||||
producer: 'alertsFixture',
|
||||
};
|
||||
const exampleAlwaysFiringAlertType: RuleType<{}, {}, {}, {}, {}, 'small' | 'medium' | 'large'> = {
|
||||
id: 'example.always-firing',
|
||||
name: 'Always firing',
|
||||
actionGroups: [
|
||||
{ id: 'small', name: 'Small t-shirt' },
|
||||
{ id: 'medium', name: 'Medium t-shirt' },
|
||||
{ id: 'large', name: 'Large t-shirt' },
|
||||
],
|
||||
defaultActionGroupId: 'small',
|
||||
minimumLicenseRequired: 'basic',
|
||||
isExportable: true,
|
||||
async executor() {},
|
||||
producer: 'alertsFixture',
|
||||
};
|
||||
|
||||
alerting.registerType(getAlwaysFiringAlertType());
|
||||
alerting.registerType(getCumulativeFiringAlertType());
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
} from 'kibana/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { InvalidatePendingApiKey } from '../../../../../../../plugins/alerting/server/types';
|
||||
import { RawAlert } from '../../../../../../../plugins/alerting/server/types';
|
||||
import { RawRule } from '../../../../../../../plugins/alerting/server/types';
|
||||
import {
|
||||
ConcreteTaskInstance,
|
||||
TaskInstance,
|
||||
|
@ -89,12 +89,12 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo
|
|||
logger,
|
||||
`/api/alerts_fixture/${id}/replace_api_key`,
|
||||
async () => {
|
||||
return await savedObjectsWithAlerts.update<RawAlert>(
|
||||
return await savedObjectsWithAlerts.update<RawRule>(
|
||||
'alert',
|
||||
id,
|
||||
{
|
||||
...(
|
||||
await encryptedSavedObjectsWithAlerts.getDecryptedAsInternalUser<RawAlert>(
|
||||
await encryptedSavedObjectsWithAlerts.getDecryptedAsInternalUser<RawRule>(
|
||||
'alert',
|
||||
id,
|
||||
{
|
||||
|
@ -154,7 +154,7 @@ export function defineRoutes(core: CoreSetup<FixtureStartDeps>, { logger }: { lo
|
|||
const savedObjectsWithAlerts = await savedObjects.getScopedClient(req, {
|
||||
includedHiddenTypes: ['alert'],
|
||||
});
|
||||
const savedAlert = await savedObjectsWithAlerts.get<RawAlert>(type, id);
|
||||
const savedAlert = await savedObjectsWithAlerts.get<RawRule>(type, id);
|
||||
const result = await retryIfConflicts(
|
||||
logger,
|
||||
`/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, {
|
||||
includedHiddenTypes: ['task', 'alert'],
|
||||
});
|
||||
const alert = await savedObjectsWithTasksAndAlerts.get<RawAlert>('alert', id);
|
||||
const alert = await savedObjectsWithTasksAndAlerts.get<RawRule>('alert', id);
|
||||
const result = await retryIfConflicts(
|
||||
logger,
|
||||
`/api/alerts_fixture/{id}/reset_task_status`,
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
import { CoreSetup } from 'src/core/server';
|
||||
import { FixtureStartDeps, FixtureSetupDeps } from './plugin';
|
||||
import { AlertType } from '../../../../../../../plugins/alerting/server';
|
||||
import { RuleType } from '../../../../../../../plugins/alerting/server';
|
||||
|
||||
export function defineAlertTypes(
|
||||
core: CoreSetup<FixtureStartDeps>,
|
||||
{ alerting }: Pick<FixtureSetupDeps, 'alerting'>
|
||||
) {
|
||||
const noopRestrictedAlertType: AlertType<{}, {}, {}, {}, {}, 'default', 'restrictedRecovered'> = {
|
||||
const noopRestrictedAlertType: RuleType<{}, {}, {}, {}, {}, 'default', 'restrictedRecovered'> = {
|
||||
id: 'test.restricted-noop',
|
||||
name: 'Test: Restricted Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -24,7 +24,7 @@ export function defineAlertTypes(
|
|||
recoveryActionGroup: { id: 'restrictedRecovered', name: 'Restricted Recovery' },
|
||||
async executor() {},
|
||||
};
|
||||
const noopUnrestrictedAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
const noopUnrestrictedAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.unrestricted-noop',
|
||||
name: 'Test: Unrestricted Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
|
|
@ -227,7 +227,7 @@ instanceStateValue: true
|
|||
alertId,
|
||||
ruleTypeId: 'test.always-firing',
|
||||
outcome: 'success',
|
||||
message: `alert executed: test.always-firing:${alertId}: 'abc'`,
|
||||
message: `rule executed: test.always-firing:${alertId}: 'abc'`,
|
||||
ruleObject: alertSearchResultWithoutDates,
|
||||
});
|
||||
break;
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
TaskManagerDoc,
|
||||
} from '../../../common/lib';
|
||||
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
|
||||
export default function createAlertTests({ getService }: FtrProviderContext) {
|
||||
|
@ -190,7 +190,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) {
|
|||
execution_status: response.body.execution_status,
|
||||
});
|
||||
|
||||
const esResponse = await es.get<SavedObject<RawAlert>>(
|
||||
const esResponse = await es.get<SavedObject<RawRule>>(
|
||||
{
|
||||
index: '.kibana',
|
||||
id: `alert:${response.body.id}`,
|
||||
|
|
|
@ -133,7 +133,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
savedObjects: [
|
||||
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
|
||||
],
|
||||
message: `alert execution start: "${alertId}"`,
|
||||
message: `rule execution start: "${alertId}"`,
|
||||
shouldHaveTask: true,
|
||||
rule: {
|
||||
id: alertId,
|
||||
|
@ -150,7 +150,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
|
||||
],
|
||||
outcome: 'success',
|
||||
message: `alert executed: test.patternFiring:${alertId}: 'abc'`,
|
||||
message: `rule executed: test.patternFiring:${alertId}: 'abc'`,
|
||||
status: executeStatuses[executeCount++],
|
||||
shouldHaveTask: true,
|
||||
rule: {
|
||||
|
@ -182,15 +182,15 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
});
|
||||
break;
|
||||
case 'new-instance':
|
||||
validateInstanceEvent(event, `created new instance: 'instance'`, false);
|
||||
validateInstanceEvent(event, `created new alert: 'instance'`, false);
|
||||
break;
|
||||
case 'recovered-instance':
|
||||
validateInstanceEvent(event, `instance 'instance' has recovered`, true);
|
||||
validateInstanceEvent(event, `alert 'instance' has recovered`, true);
|
||||
break;
|
||||
case 'active-instance':
|
||||
validateInstanceEvent(
|
||||
event,
|
||||
`active instance: 'instance' in actionGroup: 'default'`,
|
||||
`active alert: 'instance' in actionGroup: 'default'`,
|
||||
false
|
||||
);
|
||||
break;
|
||||
|
@ -344,7 +344,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
savedObjects: [
|
||||
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
|
||||
],
|
||||
message: `alert execution start: "${alertId}"`,
|
||||
message: `rule execution start: "${alertId}"`,
|
||||
shouldHaveTask: true,
|
||||
rule: {
|
||||
id: alertId,
|
||||
|
@ -361,7 +361,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
|
||||
],
|
||||
outcome: 'success',
|
||||
message: `alert executed: test.patternFiring:${alertId}: 'abc'`,
|
||||
message: `rule executed: test.patternFiring:${alertId}: 'abc'`,
|
||||
status: executeStatuses[executeCount++],
|
||||
shouldHaveTask: true,
|
||||
rule: {
|
||||
|
@ -398,10 +398,10 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
});
|
||||
break;
|
||||
case 'new-instance':
|
||||
validateInstanceEvent(event, `created new instance: 'instance'`, false);
|
||||
validateInstanceEvent(event, `created new alert: 'instance'`, false);
|
||||
break;
|
||||
case 'recovered-instance':
|
||||
validateInstanceEvent(event, `instance 'instance' has recovered`, true);
|
||||
validateInstanceEvent(event, `alert 'instance' has recovered`, true);
|
||||
break;
|
||||
case 'active-instance':
|
||||
expect(
|
||||
|
@ -411,7 +411,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
).to.be(true);
|
||||
validateInstanceEvent(
|
||||
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
|
||||
);
|
||||
break;
|
||||
|
@ -490,7 +490,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
savedObjects: [
|
||||
{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.patternFiring' },
|
||||
],
|
||||
message: `alert execution start: "${alertId}"`,
|
||||
message: `rule execution start: "${alertId}"`,
|
||||
shouldHaveTask: true,
|
||||
rule: {
|
||||
id: alertId,
|
||||
|
@ -504,7 +504,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
|
|||
spaceId: space.id,
|
||||
savedObjects: [{ type: 'alert', id: alertId, rel: 'primary', type_id: 'test.throw' }],
|
||||
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',
|
||||
status: 'error',
|
||||
reason: 'execute',
|
||||
|
|
|
@ -9,7 +9,7 @@ import expect from '@kbn/expect';
|
|||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { getUrlPrefix } from '../../../common/lib';
|
||||
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';
|
||||
|
||||
// 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 () => {
|
||||
const searchResult = await es.search<RawAlert>(
|
||||
const searchResult = await es.search<RawRule>(
|
||||
{
|
||||
index: '.kibana',
|
||||
body: {
|
||||
|
@ -221,13 +221,13 @@ export default function createGetTests({ getService }: FtrProviderContext) {
|
|||
expect(searchResult.statusCode).to.equal(200);
|
||||
expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1);
|
||||
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'
|
||||
);
|
||||
});
|
||||
|
||||
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',
|
||||
body: {
|
||||
|
@ -243,7 +243,7 @@ export default function createGetTests({ getService }: FtrProviderContext) {
|
|||
expect(searchResult.statusCode).to.equal(200);
|
||||
expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1);
|
||||
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',
|
||||
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 () => {
|
||||
const response = await es.get<{ alert: RawAlert }>(
|
||||
const response = await es.get<{ alert: RawRule }>(
|
||||
{
|
||||
index: '.kibana',
|
||||
id: 'alert:92237b30-4e03-11ec-9ab9-d980518a2d28',
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { Plugin, CoreSetup } from 'kibana/server';
|
||||
import {
|
||||
PluginSetupContract as AlertingSetup,
|
||||
AlertType,
|
||||
RuleType,
|
||||
} from '../../../../../../plugins/alerting/server';
|
||||
import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../plugins/features/server';
|
||||
|
||||
|
@ -18,7 +18,7 @@ export interface AlertingExampleDeps {
|
|||
features: FeaturesPluginSetup;
|
||||
}
|
||||
|
||||
export const noopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
export const noopAlertType: RuleType<{}, {}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.noop',
|
||||
name: 'Test: Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -29,7 +29,7 @@ export const noopAlertType: AlertType<{}, {}, {}, {}, {}, 'default'> = {
|
|||
producer: 'alerts',
|
||||
};
|
||||
|
||||
export const alwaysFiringAlertType: AlertType<
|
||||
export const alwaysFiringAlertType: RuleType<
|
||||
{ instances: Array<{ id: string; state: any }> },
|
||||
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',
|
||||
name: 'Test: Failing',
|
||||
actionGroups: [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue