diff --git a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts index 7069000ed16a0b..7e4efb2665f6b0 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/find/find_rules.ts @@ -149,16 +149,18 @@ export async function findRules( throw error; } - const rule = getAlertFromRaw( - context, + const rule = getAlertFromRaw({ + excludeFromPublicApi, id, - attributes.alertTypeId, - (fields ? pick(attributes, fields) : attributes) as RawRule, + includeLegacyId: false, + includeSnoozeData, + isSystemAction: context.isSystemAction, + logger: context.logger, + rawRule: (fields ? pick(attributes, fields) : attributes) as RawRule, references, - false, - excludeFromPublicApi, - includeSnoozeData - ); + ruleTypeId: attributes.alertTypeId, + ruleTypeRegistry: context.ruleTypeRegistry, + }); // collect SIEM rule for further formatting legacy actions if (attributes.consumer === AlertConsumers.SIEM) { diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index ba1eff19ff4266..fd209ef009d73a 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -606,7 +606,6 @@ export class AlertingPlugin { encryptedSavedObjectsClient, eventLogger: this.eventLogger!, executionContext: core.executionContext, - getRulesClientWithRequest, kibanaBaseUrl: this.kibanaBaseUrl, logger, maintenanceWindowsService: new MaintenanceWindowsService({ diff --git a/x-pack/plugins/alerting/server/rules_client.mock.ts b/x-pack/plugins/alerting/server/rules_client.mock.ts index b7e43cacd310fe..0616591cbe565b 100644 --- a/x-pack/plugins/alerting/server/rules_client.mock.ts +++ b/x-pack/plugins/alerting/server/rules_client.mock.ts @@ -52,10 +52,8 @@ const createRulesClientMock = () => { bulkDisableRules: jest.fn(), snooze: jest.fn(), unsnooze: jest.fn(), - clearExpiredSnoozes: jest.fn(), runSoon: jest.fn(), clone: jest.fn(), - getAlertFromRaw: jest.fn(), getScheduleFrequency: jest.fn(), bulkUntrackAlerts: jest.fn(), }; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts b/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts index 7c40ef31cd8aee..644ad0626de6a6 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts @@ -141,13 +141,15 @@ export async function createRuleSavedObject; } - return getAlertFromRaw( - context, - createdAlert.id, - createdAlert.attributes.alertTypeId, - createdAlert.attributes, + return getAlertFromRaw({ + excludeFromPublicApi: true, + id: createdAlert.id, + includeLegacyId: false, + isSystemAction: context.isSystemAction, + logger: context.logger, + rawRule: createdAlert.attributes, references, - false, - true - ); + ruleTypeId: createdAlert.attributes.alertTypeId, + ruleTypeRegistry: context.ruleTypeRegistry, + }); } diff --git a/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts b/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts index ac337001099bd7..2e9964f6ebfa74 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts @@ -6,7 +6,7 @@ */ import { omit, isEmpty } from 'lodash'; -import { SavedObjectReference } from '@kbn/core/server'; +import { Logger, SavedObjectReference } from '@kbn/core/server'; import { Rule, PartialRule, @@ -15,6 +15,7 @@ import { RuleTypeParams, RuleWithLegacyId, PartialRuleWithLegacyId, + RuleTypeRegistry, } from '../../types'; import { ruleExecutionStatusFromRaw, @@ -24,11 +25,11 @@ import { import { UntypedNormalizedRuleType } from '../../rule_type_registry'; import { getActiveScheduledSnoozes } from '../../lib/is_rule_snoozed'; import { injectReferencesIntoParams } from '../common'; -import { RulesClientContext } from '../types'; import { transformRawActionsToDomainActions, transformRawActionsToDomainSystemActions, } from '../../application/rule/transforms/transform_raw_actions_to_domain_actions'; +import { fieldsToExcludeFromPublicApi } from '../rules_client'; export interface GetAlertFromRawParams { id: string; @@ -41,35 +42,52 @@ export interface GetAlertFromRawParams { omitGeneratedValues?: boolean; } +interface GetAlertFromRawOpts { + excludeFromPublicApi?: boolean; + id: string; + includeLegacyId?: boolean; + includeSnoozeData?: boolean; + isSystemAction: (actionId: string) => boolean; + logger: Logger; + omitGeneratedValues?: boolean; + rawRule: RawRule; + references: SavedObjectReference[] | undefined; + ruleTypeId: string; + ruleTypeRegistry: RuleTypeRegistry; +} + +type GetPartialRuleFromRawOpts = Omit & { + ruleType: UntypedNormalizedRuleType; +}; /** * @deprecated in favor of transformRuleAttributesToRuleDomain */ export function getAlertFromRaw( - context: RulesClientContext, - id: string, - ruleTypeId: string, - rawRule: RawRule, - references: SavedObjectReference[] | undefined, - includeLegacyId: boolean = false, - excludeFromPublicApi: boolean = false, - includeSnoozeData: boolean = false, - omitGeneratedValues: boolean = true + opts: GetAlertFromRawOpts ): Rule | RuleWithLegacyId { - const ruleType = context.ruleTypeRegistry.get(ruleTypeId); + const { + excludeFromPublicApi = false, + includeLegacyId = false, + includeSnoozeData = false, + omitGeneratedValues = true, + } = opts; + const ruleType = opts.ruleTypeRegistry.get(opts.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 RawRule, it is safe // to cast the result to an Alert - const res = getPartialRuleFromRaw( - context, - id, - ruleType, - rawRule, - references, - includeLegacyId, + const res = getPartialRuleFromRaw({ excludeFromPublicApi, + id: opts.id, + includeLegacyId, includeSnoozeData, - omitGeneratedValues - ); + isSystemAction: opts.isSystemAction, + logger: opts.logger, + omitGeneratedValues, + rawRule: opts.rawRule, + references: opts.references, + ruleTypeId: opts.ruleTypeId, + ruleType, + }); // include to result because it is for internal rules client usage if (includeLegacyId) { return res as RuleWithLegacyId; @@ -78,11 +96,18 @@ export function getAlertFromRaw( return omit(res, ['legacyId']) as Rule; } -export function getPartialRuleFromRaw( - context: RulesClientContext, - id: string, - ruleType: UntypedNormalizedRuleType, - { +function getPartialRuleFromRaw( + opts: GetPartialRuleFromRawOpts +): PartialRule | PartialRuleWithLegacyId { + const { + excludeFromPublicApi = false, + includeLegacyId = false, + includeSnoozeData = false, + omitGeneratedValues = true, + rawRule, + } = opts; + + const { createdAt, updatedAt, meta, @@ -99,13 +124,8 @@ export function getPartialRuleFromRaw( lastRun, isSnoozedUntil: DoNotUseIsSNoozedUntil, ...partialRawRule - }: Partial, - references: SavedObjectReference[] | undefined, - includeLegacyId: boolean = false, - excludeFromPublicApi: boolean = false, - includeSnoozeData: boolean = false, - omitGeneratedValues: boolean = true -): PartialRule | PartialRuleWithLegacyId { + } = rawRule; + const snoozeScheduleDates = snoozeSchedule?.map((s) => ({ ...s, rRule: { @@ -125,31 +145,36 @@ export function getPartialRuleFromRaw( const includeMonitoring = monitoring && !excludeFromPublicApi; const rule: PartialRule = { - id, + id: opts.id, notifyWhen, - ...omit(partialRawRule, excludeFromPublicApi ? [...context.fieldsToExcludeFromPublicApi] : ''), + ...omit(partialRawRule, excludeFromPublicApi ? [...fieldsToExcludeFromPublicApi] : ''), // we currently only support the Interval Schedule type // Once we support additional types, this type signature will likely change schedule: schedule as IntervalSchedule, actions: actions ? transformRawActionsToDomainActions({ - ruleId: id, + ruleId: opts.id, actions, - references: references || [], - isSystemAction: context.isSystemAction, + references: opts.references || [], + isSystemAction: opts.isSystemAction, omitGeneratedValues, }) : [], systemActions: actions ? transformRawActionsToDomainSystemActions({ - ruleId: id, + ruleId: opts.id, actions, - references: references || [], - isSystemAction: context.isSystemAction, + references: opts.references || [], + isSystemAction: opts.isSystemAction, omitGeneratedValues, }) : [], - params: injectReferencesIntoParams(id, ruleType, params, references || []) as Params, + params: injectReferencesIntoParams( + opts.id, + opts.ruleType, + params, + opts.references || [] + ) as Params, ...(excludeFromPublicApi ? {} : { snoozeSchedule: snoozeScheduleDates ?? [] }), ...(includeSnoozeData && !excludeFromPublicApi ? { @@ -164,10 +189,10 @@ export function getPartialRuleFromRaw( ...(createdAt ? { createdAt: new Date(createdAt) } : {}), ...(scheduledTaskId ? { scheduledTaskId } : {}), ...(executionStatus - ? { executionStatus: ruleExecutionStatusFromRaw(context.logger, id, executionStatus) } + ? { executionStatus: ruleExecutionStatusFromRaw(opts.logger, opts.id, executionStatus) } : {}), ...(includeMonitoring - ? { monitoring: convertMonitoringFromRawAndVerify(context.logger, id, monitoring) } + ? { monitoring: convertMonitoringFromRawAndVerify(opts.logger, opts.id, monitoring) } : {}), ...(nextRun ? { nextRun: new Date(nextRun) } : {}), ...(lastRun @@ -193,7 +218,7 @@ export function getPartialRuleFromRaw( // Need the `rule` object to build a URL if (!excludeFromPublicApi) { const viewInAppRelativeUrl = - ruleType.getViewInAppRelativeUrl && ruleType.getViewInAppRelativeUrl({ rule }); + opts.ruleType.getViewInAppRelativeUrl && opts.ruleType.getViewInAppRelativeUrl({ rule }); if (viewInAppRelativeUrl) { rule.viewInAppRelativeUrl = viewInAppRelativeUrl; } diff --git a/x-pack/plugins/alerting/server/rules_client/methods/clear_expired_snoozes.ts b/x-pack/plugins/alerting/server/rules_client/methods/clear_expired_snoozes.ts deleted file mode 100644 index 70f0e8a29eac25..00000000000000 --- a/x-pack/plugins/alerting/server/rules_client/methods/clear_expired_snoozes.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { RuleTypeParams, SanitizedRule } from '../../../common'; -import { partiallyUpdateRule } from '../../saved_objects'; -import { isSnoozeExpired } from '../../lib'; -import { RulesClientContext } from '../types'; -import { updateMeta } from '../lib'; - -export async function clearExpiredSnoozes( - context: RulesClientContext, - { - rule, - version, - }: { rule: Pick, 'id' | 'snoozeSchedule'>; version?: string } -): Promise { - const snoozeSchedule = rule.snoozeSchedule - ? rule.snoozeSchedule.filter((s) => { - try { - return !isSnoozeExpired(s); - } catch (e) { - context.logger.error(`Error checking for expiration of snooze ${s.id}: ${e}`); - return true; - } - }) - : []; - - if (snoozeSchedule.length === rule.snoozeSchedule?.length) return; - - const updateAttributes = updateMeta(context, { - snoozeSchedule, - updatedBy: await context.getUserName(), - updatedAt: new Date().toISOString(), - }); - - const updateOptions = { version, refresh: false }; - - await partiallyUpdateRule( - context.unsecuredSavedObjectsClient, - rule.id, - updateAttributes, - updateOptions - ); -} diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index 343fbec059940e..80f9b82733a9df 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -57,14 +57,12 @@ import { bulkEnableRules, BulkEnableRulesParams } from '../application/rule/meth import { enableRule } from '../application/rule/methods/enable_rule/enable_rule'; import { updateRuleApiKey } from '../application/rule/methods/update_api_key/update_rule_api_key'; import { disableRule } from '../application/rule/methods/disable/disable_rule'; -import { clearExpiredSnoozes } from './methods/clear_expired_snoozes'; import { muteInstance } from '../application/rule/methods/mute_alert/mute_instance'; import { muteAll } from './methods/mute_all'; import { unmuteAll } from './methods/unmute_all'; import { unmuteInstance } from '../application/rule/methods/unmute_alert/unmute_instance'; import { runSoon } from './methods/run_soon'; import { listRuleTypes } from './methods/list_rule_types'; -import { getAlertFromRaw, GetAlertFromRawParams } from './lib/get_alert_from_raw'; import { getScheduleFrequency } from '../application/rule/methods/get_schedule_frequency/get_schedule_frequency'; import { bulkUntrackAlerts, @@ -84,7 +82,7 @@ export type ConstructorOptions = Omit< 'fieldsToExcludeFromPublicApi' | 'minimumScheduleIntervalInMs' >; -const fieldsToExcludeFromPublicApi: Array = [ +export const fieldsToExcludeFromPublicApi: Array = [ 'monitoring', 'mapped_params', 'snoozeSchedule', @@ -174,11 +172,6 @@ export class RulesClient { public snooze = (options: SnoozeRuleOptions) => snoozeRule(this.context, options); public unsnooze = (options: UnsnoozeParams) => unsnoozeRule(this.context, options); - public clearExpiredSnoozes = (options: { - rule: Pick, 'id' | 'snoozeSchedule'>; - version?: string; - }) => clearExpiredSnoozes(this.context, options); - public muteAll = (options: { id: string }) => muteAll(this.context, options); public unmuteAll = (options: { id: string }) => unmuteAll(this.context, options); public muteInstance = (options: MuteAlertParams) => muteInstance(this.context, options); @@ -214,17 +207,4 @@ export class RulesClient { public getTags = (params: RuleTagsParams) => getRuleTags(this.context, params); public getScheduleFrequency = () => getScheduleFrequency(this.context); - - public getAlertFromRaw = (params: GetAlertFromRawParams) => - getAlertFromRaw( - this.context, - params.id, - params.ruleTypeId, - params.rawRule, - params.references, - params.includeLegacyId, - params.excludeFromPublicApi, - params.includeSnoozeData, - params.omitGeneratedValues - ); } diff --git a/x-pack/plugins/alerting/server/rules_client/tests/clear_expired_snoozes.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/clear_expired_snoozes.test.ts deleted file mode 100644 index 99f895a9866b22..00000000000000 --- a/x-pack/plugins/alerting/server/rules_client/tests/clear_expired_snoozes.test.ts +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; -import sinon from 'sinon'; -import { RulesClient, ConstructorOptions } from '../rules_client'; -import { - savedObjectsClientMock, - loggingSystemMock, - savedObjectsRepositoryMock, - uiSettingsServiceMock, -} from '@kbn/core/server/mocks'; -import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; -import { ruleTypeRegistryMock } from '../../rule_type_registry.mock'; -import { alertingAuthorizationMock } from '../../authorization/alerting_authorization.mock'; -import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; -import { actionsAuthorizationMock } from '@kbn/actions-plugin/server/mocks'; -import { AlertingAuthorization } from '../../authorization/alerting_authorization'; -import { ActionsAuthorization } from '@kbn/actions-plugin/server'; -import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { getBeforeSetup, mockedDateString } from './lib'; -import { eventLoggerMock } from '@kbn/event-log-plugin/server/event_logger.mock'; -import { TaskStatus } from '@kbn/task-manager-plugin/server'; -import { RuleSnooze } from '../../types'; -import { ConnectorAdapterRegistry } from '../../connector_adapters/connector_adapter_registry'; -import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects'; -import { backfillClientMock } from '../../backfill_client/backfill_client.mock'; - -jest.mock('../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation', () => ({ - bulkMarkApiKeysForInvalidation: jest.fn(), -})); - -jest.mock('uuid', () => ({ - v4: () => '5f6aa57d-3e22-484e-bae8-cbed868f4d28', -})); - -let clock: sinon.SinonFakeTimers; - -const taskManager = taskManagerMock.createStart(); -const ruleTypeRegistry = ruleTypeRegistryMock.create(); -const unsecuredSavedObjectsClient = savedObjectsClientMock.create(); -const encryptedSavedObjects = encryptedSavedObjectsMock.createClient(); -const authorization = alertingAuthorizationMock.create(); -const actionsAuthorization = actionsAuthorizationMock.create(); -const auditLogger = auditLoggerMock.create(); -const eventLogger = eventLoggerMock.create(); -const internalSavedObjectsRepository = savedObjectsRepositoryMock.create(); - -const kibanaVersion = 'v7.10.0'; -const rulesClientParams: jest.Mocked = { - taskManager, - ruleTypeRegistry, - unsecuredSavedObjectsClient, - authorization: authorization as unknown as AlertingAuthorization, - actionsAuthorization: actionsAuthorization as unknown as ActionsAuthorization, - spaceId: 'default', - namespace: 'default', - maxScheduledPerMinute: 10000, - minimumScheduleInterval: { value: '1m', enforce: false }, - getUserName: jest.fn(), - createAPIKey: jest.fn(), - logger: loggingSystemMock.create().get(), - internalSavedObjectsRepository, - encryptedSavedObjectsClient: encryptedSavedObjects, - getActionsClient: jest.fn(), - getEventLogClient: jest.fn(), - kibanaVersion, - auditLogger, - eventLogger, - isAuthenticationTypeAPIKey: jest.fn(), - getAuthenticationAPIKey: jest.fn(), - connectorAdapterRegistry: new ConnectorAdapterRegistry(), - getAlertIndicesAlias: jest.fn(), - alertsService: null, - backfillClient: backfillClientMock.create(), - uiSettings: uiSettingsServiceMock.createStartContract(), - isSystemAction: jest.fn(), -}; - -describe('clearExpiredSnoozes()', () => { - let rulesClient: RulesClient; - - beforeAll(() => { - clock = sinon.useFakeTimers(new Date(mockedDateString)); - }); - afterAll(() => clock.restore()); - - beforeEach(() => { - clock.reset(); - getBeforeSetup(rulesClientParams, taskManager, ruleTypeRegistry); - (auditLogger.log as jest.Mock).mockClear(); - rulesClient = new RulesClient(rulesClientParams); - rulesClientParams.createAPIKey.mockResolvedValue({ - apiKeysEnabled: false, - }); - }); - - test('clears expired unscheduled snoozes and leaves unexpired scheduled snoozes', async () => { - const { attributes, id } = setupTestWithSnoozeSchedule([ - { - duration: 1000, - rRule: { - tzid: 'UTC', - dtstart: moment().subtract(1, 'd').toISOString(), - count: 1, - }, - }, - { - id: '1', - duration: 1000, - rRule: { - tzid: 'UTC', - dtstart: moment().add(1, 'd').toISOString(), - count: 1, - }, - }, - ]); - await rulesClient.clearExpiredSnoozes({ rule: { ...attributes, id } }); - expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith( - RULE_SAVED_OBJECT_TYPE, - '1', - { - updatedAt: '2019-02-12T21:01:22.479Z', - updatedBy: 'elastic', - snoozeSchedule: [ - { - id: '1', - duration: 1000, - rRule: { - tzid: 'UTC', - dtstart: moment().add(1, 'd').toISOString(), - count: 1, - }, - }, - ], - }, - { - refresh: false, - } - ); - }); - test('clears expired scheduled snoozes and leaves unexpired ones', async () => { - const { attributes, id } = setupTestWithSnoozeSchedule([ - { - id: '1', - duration: 1000, - rRule: { - tzid: 'UTC', - dtstart: moment().subtract(1, 'd').toISOString(), - count: 1, - }, - }, - { - id: '2', - duration: 1000, - rRule: { - tzid: 'UTC', - dtstart: moment().add(1, 'd').toISOString(), - count: 1, - }, - }, - ]); - await rulesClient.clearExpiredSnoozes({ rule: { ...attributes, id } }); - expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith( - RULE_SAVED_OBJECT_TYPE, - '1', - { - updatedAt: '2019-02-12T21:01:22.479Z', - updatedBy: 'elastic', - snoozeSchedule: [ - { - id: '2', - duration: 1000, - rRule: { - tzid: 'UTC', - dtstart: moment().add(1, 'd').toISOString(), - count: 1, - }, - }, - ], - }, - { - refresh: false, - } - ); - }); - test('does nothing when no snoozes are expired', async () => { - const { attributes, id } = setupTestWithSnoozeSchedule([ - { - duration: 1000 * 24 * 60 * 60 * 3, // 3 days - rRule: { - tzid: 'UTC', - dtstart: moment().subtract(1, 'd').toISOString(), - count: 1, - }, - }, - { - id: '2', - duration: 1000, - rRule: { - tzid: 'UTC', - dtstart: moment().add(1, 'd').toISOString(), - count: 1, - }, - }, - ]); - await rulesClient.clearExpiredSnoozes({ rule: { ...attributes, id } }); - expect(unsecuredSavedObjectsClient.update).not.toHaveBeenCalled(); - }); -}); - -function setupTestWithSnoozeSchedule(snoozeSchedule: RuleSnooze) { - const rule = { - id: '1', - type: RULE_SAVED_OBJECT_TYPE, - attributes: { - name: 'name', - consumer: 'myApp', - schedule: { interval: '10s' }, - alertTypeId: 'myType', - enabled: true, - apiKey: 'MTIzOmFiYw==', - apiKeyOwner: 'elastic', - actions: [ - { - group: 'default', - id: '1', - actionTypeId: '1', - actionRef: '1', - params: { - foo: true, - }, - }, - ], - snoozeSchedule, - }, - version: '123', - references: [], - }; - - encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValue(rule); - unsecuredSavedObjectsClient.get.mockResolvedValue(rule); - taskManager.schedule.mockResolvedValue({ - id: '1', - scheduledAt: new Date(), - attempts: 0, - status: TaskStatus.Idle, - runAt: new Date(), - state: {}, - params: {}, - taskType: '', - startedAt: null, - retryAt: null, - ownerId: null, - }); - return rule; -} diff --git a/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.test.ts b/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.test.ts index 294bc814815406..5e53834bf73d85 100644 --- a/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.test.ts @@ -263,6 +263,17 @@ const DefaultAttributesForEsUpdate = { }, }, }, + snoozeSchedule: [ + { + duration: 1000, + id: '1', + rRule: { + count: 1, + dtstart: '2019-02-13T21:01:22.479Z', + tzid: 'UTC', + }, + }, + ], }; const AttributesForEsUpdateWithUnallowedFields = { diff --git a/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.ts b/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.ts index f9b4da5ed767b9..24af1da5af62be 100644 --- a/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.ts +++ b/x-pack/plugins/alerting/server/saved_objects/partially_update_rule.ts @@ -79,6 +79,7 @@ const RuleAttributesAllowedForPartialUpdate = [ 'monitoring', 'nextRun', 'running', + 'snoozeSchedule', ]; // direct, partial update to a rule saved object via ElasticsearchClient diff --git a/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts index 59e7e9d548f5cb..0e0d7983e59ff5 100644 --- a/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.test.ts @@ -30,7 +30,6 @@ import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/us import { AdHocTaskRunner } from './ad_hoc_task_runner'; import { TaskRunnerContext } from './types'; import { backfillClientMock } from '../backfill_client/backfill_client.mock'; -import { rulesClientMock } from '../rules_client.mock'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { AlertingEventLogger, @@ -143,7 +142,6 @@ const elasticsearchService = elasticsearchServiceMock.createInternalStart(); const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient(); const internalSavedObjectsRepository = savedObjectsRepositoryMock.create(); const maintenanceWindowsService = maintenanceWindowsServiceMock.create(); -const rulesClient = rulesClientMock.create(); const ruleRunMetricsStore = ruleRunMetricsStoreMock.create(); const rulesSettingsService = rulesSettingsServiceMock.create(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); @@ -166,7 +164,6 @@ const taskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType eventLogger: eventLoggerMock.create(), executionContext: executionContextServiceMock.createInternalStartContract(), maintenanceWindowsService, - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), kibanaBaseUrl: 'https://localhost:5601', logger, maxAlerts: 1000, diff --git a/x-pack/plugins/alerting/server/task_runner/lib/clear_expired_snoozes.test.ts b/x-pack/plugins/alerting/server/task_runner/lib/clear_expired_snoozes.test.ts new file mode 100644 index 00000000000000..756af0349fb6a7 --- /dev/null +++ b/x-pack/plugins/alerting/server/task_runner/lib/clear_expired_snoozes.test.ts @@ -0,0 +1,250 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment'; +import sinon from 'sinon'; +import { Logger } from '@kbn/core/server'; +import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { RuleSnooze } from '../../types'; +import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects'; +import { clearExpiredSnoozes } from './clear_expired_snoozes'; +import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; + +let clock: sinon.SinonFakeTimers; + +const mockLogger = loggingSystemMock.create().get() as jest.Mocked; +const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + +describe('clearExpiredSnoozes()', () => { + beforeAll(() => { + clock = sinon.useFakeTimers(new Date('2019-02-12T21:01:22.479Z')); + }); + afterAll(() => clock.restore()); + + beforeEach(() => { + jest.clearAllMocks(); + clock.reset(); + }); + + test('clears expired unscheduled snoozes and leaves unexpired scheduled snoozes', async () => { + const { attributes, id } = getRule([ + { + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().subtract(1, 'd').toISOString(), + count: 1, + }, + }, + { + id: '1', + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().add(1, 'd').toISOString(), + count: 1, + }, + }, + ]); + await clearExpiredSnoozes({ + esClient, + logger: mockLogger, + rule: { ...attributes, id }, + }); + expect(esClient.update).toHaveBeenCalledWith({ + doc: { + alert: { + snoozeSchedule: [ + { + duration: 1000, + id: '1', + rRule: { + count: 1, + dtstart: '2019-02-13T21:01:22.479Z', + tzid: 'UTC', + }, + }, + ], + }, + }, + id: 'alert:1', + index: ALERTING_CASES_SAVED_OBJECT_INDEX, + }); + }); + + test('clears expired scheduled snoozes and leaves unexpired ones', async () => { + const { attributes, id } = getRule([ + { + id: '1', + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().subtract(1, 'd').toISOString(), + count: 1, + }, + }, + { + id: '2', + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().add(1, 'd').toISOString(), + count: 1, + }, + }, + ]); + await clearExpiredSnoozes({ + esClient, + logger: mockLogger, + rule: { ...attributes, id }, + }); + expect(esClient.update).toHaveBeenCalledWith({ + doc: { + alert: { + snoozeSchedule: [ + { + id: '2', + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().add(1, 'd').toISOString(), + count: 1, + }, + }, + ], + }, + }, + id: 'alert:1', + index: ALERTING_CASES_SAVED_OBJECT_INDEX, + }); + }); + + test('passes version if provided', async () => { + const { attributes, id } = getRule([ + { + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().subtract(1, 'd').toISOString(), + count: 1, + }, + }, + { + id: '1', + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().add(1, 'd').toISOString(), + count: 1, + }, + }, + ]); + await clearExpiredSnoozes({ + esClient, + logger: mockLogger, + rule: { ...attributes, id }, + version: 'WzQsMV0=', + }); + expect(esClient.update).toHaveBeenCalledWith({ + doc: { + alert: { + snoozeSchedule: [ + { + id: '1', + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().add(1, 'd').toISOString(), + count: 1, + }, + }, + ], + }, + }, + id: 'alert:1', + if_primary_term: 1, + if_seq_no: 4, + index: ALERTING_CASES_SAVED_OBJECT_INDEX, + }); + }); + + test('does nothing when no snoozes are expired', async () => { + const { attributes, id } = getRule([ + { + duration: 1000 * 24 * 60 * 60 * 3, // 3 days + rRule: { + tzid: 'UTC', + dtstart: moment().subtract(1, 'd').toISOString(), + count: 1, + }, + }, + { + id: '2', + duration: 1000, + rRule: { + tzid: 'UTC', + dtstart: moment().add(1, 'd').toISOString(), + count: 1, + }, + }, + ]); + await clearExpiredSnoozes({ + esClient, + logger: mockLogger, + rule: { ...attributes, id }, + }); + expect(esClient.update).not.toHaveBeenCalled(); + }); + + test('does nothing when empty snooze schedule', async () => { + const { attributes, id } = getRule([]); + await clearExpiredSnoozes({ + esClient, + logger: mockLogger, + rule: { ...attributes, id }, + }); + expect(esClient.update).not.toHaveBeenCalled(); + }); + + test('does nothing when undefined snooze schedule', async () => { + const { attributes, id } = getRule(undefined); + await clearExpiredSnoozes({ + esClient, + logger: mockLogger, + rule: { ...attributes, id }, + }); + expect(esClient.update).not.toHaveBeenCalled(); + }); +}); + +const getRule = (snoozeSchedule: RuleSnooze | undefined) => ({ + id: '1', + type: RULE_SAVED_OBJECT_TYPE, + attributes: { + name: 'name', + consumer: 'myApp', + schedule: { interval: '10s' }, + alertTypeId: 'myType', + enabled: true, + apiKey: 'MTIzOmFiYw==', + apiKeyOwner: 'elastic', + actions: [ + { + group: 'default', + id: '1', + actionTypeId: '1', + actionRef: '1', + params: { + foo: true, + }, + }, + ], + snoozeSchedule, + }, + version: 'WzQsMV0=', + references: [], +}); diff --git a/x-pack/plugins/alerting/server/task_runner/lib/clear_expired_snoozes.ts b/x-pack/plugins/alerting/server/task_runner/lib/clear_expired_snoozes.ts new file mode 100644 index 00000000000000..3850f99fde0058 --- /dev/null +++ b/x-pack/plugins/alerting/server/task_runner/lib/clear_expired_snoozes.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { RuleTypeParams, SanitizedRule } from '@kbn/alerting-types'; +import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { isSnoozeExpired } from '../../lib'; +import { partiallyUpdateRuleWithEs } from '../../saved_objects'; + +interface ClearExpiredSnoozesOpts { + esClient: ElasticsearchClient; + logger: Logger; + rule: Pick, 'id' | 'snoozeSchedule'>; + version?: string; +} +export async function clearExpiredSnoozes(opts: ClearExpiredSnoozesOpts): Promise { + const { esClient, logger, rule, version } = opts; + + if (!rule.snoozeSchedule || !rule.snoozeSchedule.length) return; + + const snoozeSchedule = rule.snoozeSchedule + ? rule.snoozeSchedule.filter((s) => { + try { + return !isSnoozeExpired(s); + } catch (e) { + logger.error(`Error checking for expiration of snooze ${s.id}: ${e}`); + return true; + } + }) + : []; + + if (snoozeSchedule.length === rule.snoozeSchedule?.length) return; + + const updateAttributes = { snoozeSchedule }; + + const updateOptions = { version, refresh: false }; + + await partiallyUpdateRuleWithEs(esClient, rule.id, updateAttributes, updateOptions); +} diff --git a/x-pack/plugins/alerting/server/task_runner/lib/index.ts b/x-pack/plugins/alerting/server/task_runner/lib/index.ts index 08134fd068f353..2ba0f37a4e6d33 100644 --- a/x-pack/plugins/alerting/server/task_runner/lib/index.ts +++ b/x-pack/plugins/alerting/server/task_runner/lib/index.ts @@ -9,3 +9,4 @@ export { partiallyUpdateAdHocRun } from './partially_update_ad_hoc_run'; export { processRunResults } from './process_run_result'; export { withAlertingSpan } from './with_alerting_span'; export { createTaskRunnerLogger } from './task_runner_logger'; +export { clearExpiredSnoozes } from './clear_expired_snoozes'; diff --git a/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts b/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts index 4524c08b56688d..1d4741f84749c6 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_loader.test.ts @@ -8,6 +8,8 @@ import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { CoreKibanaRequest, SavedObjectsErrorHelpers } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; +import { Logger } from '@kbn/core/server'; +import { loggingSystemMock } from '@kbn/core/server/mocks'; import { getDecryptedRule, @@ -16,19 +18,22 @@ import { } from './rule_loader'; import { TaskRunnerContext } from './types'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; -import { rulesClientMock } from '../rules_client.mock'; import { Rule } from '../types'; import { MONITORING_HISTORY_LIMIT, RuleExecutionStatusErrorReasons } from '../../common'; import { getReasonFromError } from '../lib/error_with_reason'; import { mockedRawRuleSO, mockedRule } from './fixtures'; import { RULE_SAVED_OBJECT_TYPE } from '../saved_objects'; import { getErrorSource, TaskErrorSource } from '@kbn/task-manager-plugin/server/task_running'; +import { getAlertFromRaw } from '../rules_client/lib/get_alert_from_raw'; // create mocks -const rulesClient = rulesClientMock.create(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.createClient(); const mockBasePathService = { set: jest.fn() }; +const mockLogger = loggingSystemMock.create().get() as jest.Mocked; + +jest.mock('../rules_client/lib/get_alert_from_raw'); +const mockGetAlertFromRaw = getAlertFromRaw as jest.MockedFunction; // assign default parameters/data const apiKey = mockedRawRuleSO.attributes.apiKey!; @@ -49,6 +54,7 @@ describe('rule_loader', () => { }); const getDefaultValidateRuleParams = (ruleEnabled: boolean = true) => ({ + logger: mockLogger, paramValidator, ruleId, spaceId, @@ -70,7 +76,17 @@ describe('rule_loader', () => { consumer, }) ); - contextMock = getTaskRunnerContext(ruleParams, MONITORING_HISTORY_LIMIT); + mockGetAlertFromRaw.mockReturnValue({ + name: ruleName, + alertTypeId: ruleTypeId, + params: ruleParams, + monitoring: { + run: { + history: new Array(MONITORING_HISTORY_LIMIT), + }, + }, + } as Rule); + contextMock = getTaskRunnerContext(); context = contextMock as unknown as TaskRunnerContext; }); @@ -91,7 +107,6 @@ describe('rule_loader', () => { expect(result.rule.alertTypeId).toBe(ruleTypeId); expect(result.rule.name).toBe(ruleName); expect(result.rule.params).toBe(ruleParams); - expect(result.rulesClient).toBe(rulesClient); expect(result.validatedParams).toEqual(ruleParams); expect(result.version).toBe('1'); }); @@ -133,7 +148,17 @@ describe('rule_loader', () => { }); test('test throws when rule params fail validation', async () => { - contextMock = getTaskRunnerContext({ bar: 'foo' }, MONITORING_HISTORY_LIMIT); + mockGetAlertFromRaw.mockReturnValueOnce({ + name: ruleName, + alertTypeId: ruleTypeId, + params: { bar: 'foo' }, + monitoring: { + run: { + history: new Array(MONITORING_HISTORY_LIMIT), + }, + }, + } as Rule); + contextMock = getTaskRunnerContext(); context = contextMock as unknown as TaskRunnerContext; let outcome = 'success'; try { @@ -284,26 +309,10 @@ function mockGetDecrypted(attributes: { apiKey?: string; enabled: boolean; consu } // return enough of TaskRunnerContext that rule_loader needs -function getTaskRunnerContext(ruleParameters: unknown, historyElements: number) { +function getTaskRunnerContext() { return { spaceIdToNamespace: jest.fn(), encryptedSavedObjectsClient: encryptedSavedObjects, basePathService: mockBasePathService, - getRulesClientWithRequest, }; - - function getRulesClientWithRequest() { - // only need get() mocked - rulesClient.getAlertFromRaw.mockReturnValue({ - name: ruleName, - alertTypeId: ruleTypeId, - params: ruleParameters, - monitoring: { - run: { - history: new Array(historyElements), - }, - }, - } as Rule); - return rulesClient; - } } diff --git a/x-pack/plugins/alerting/server/task_runner/rule_loader.ts b/x-pack/plugins/alerting/server/task_runner/rule_loader.ts index ae80b03bd0b4ee..3dd0dc8c53a55f 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_loader.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_loader.ts @@ -10,6 +10,7 @@ import { CoreKibanaRequest, FakeRawRequest, Headers, + Logger, SavedObject, SavedObjectReference, SavedObjectsErrorHelpers, @@ -25,6 +26,7 @@ import { } from '../types'; import { MONITORING_HISTORY_LIMIT, RuleTypeParams } from '../../common'; import { RULE_SAVED_OBJECT_TYPE } from '../saved_objects'; +import { getAlertFromRaw } from '../rules_client/lib'; interface RuleData { rawRule: RawRule; @@ -34,6 +36,7 @@ interface RuleData { interface ValidateRuleAndCreateFakeRequestParams { context: TaskRunnerContext; + logger: Logger; paramValidator?: RuleTypeParamsValidator; ruleData: RuleData; ruleId: string; @@ -52,6 +55,7 @@ export function validateRuleAndCreateFakeRequest( ): RunRuleParams { const { context, + logger, paramValidator, ruleData: { rawRule, references, version }, ruleId, @@ -72,14 +76,16 @@ export function validateRuleAndCreateFakeRequest( } const fakeRequest = getFakeKibanaRequest(context, spaceId, apiKey); - const rulesClient = context.getRulesClientWithRequest(fakeRequest); - const rule = rulesClient.getAlertFromRaw({ + const rule = getAlertFromRaw({ id: ruleId, - ruleTypeId, - rawRule, - references, includeLegacyId: false, + isSystemAction: (actionId: string) => context.actionsPlugin.isSystemActionConnector(actionId), + logger, omitGeneratedValues: false, + rawRule, + references, + ruleTypeId, + ruleTypeRegistry, }); try { @@ -112,7 +118,6 @@ export function validateRuleAndCreateFakeRequest( apiKey, fakeRequest, rule, - rulesClient, validatedParams, version, }; diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index e06c260109b762..eb531f0e00b886 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -40,7 +40,7 @@ import { } from '@kbn/core/server/mocks'; import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; import { actionsMock, actionsClientMock } from '@kbn/actions-plugin/server/mocks'; -import { alertsMock, rulesClientMock } from '../mocks'; +import { alertsMock } from '../mocks'; import { eventLoggerMock } from '@kbn/event-log-plugin/server/event_logger.mock'; import { IEventLogger } from '@kbn/event-log-plugin/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; @@ -79,6 +79,7 @@ import { AlertingEventLogger, ContextOpts, } from '../lib/alerting_event_logger/alerting_event_logger'; +import { getAlertFromRaw } from '../rules_client/lib/get_alert_from_raw'; import { alertingEventLoggerMock } from '../lib/alerting_event_logger/alerting_event_logger.mock'; import { SharePluginStart } from '@kbn/share-plugin/server'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; @@ -109,6 +110,9 @@ jest.mock('../lib/wrap_scoped_cluster_client', () => ({ jest.mock('../lib/alerting_event_logger/alerting_event_logger'); jest.mock('../monitoring/rule_result_service'); +jest.mock('../rules_client/lib/get_alert_from_raw'); +const mockGetAlertFromRaw = getAlertFromRaw as jest.MockedFunction; + jest.spyOn(getExecutorServicesModule, 'getExecutorServices'); let fakeTimer: sinon.SinonFakeTimers; @@ -145,7 +149,6 @@ describe('Task Runner', () => { const backfillClient = backfillClientMock.create(); const services = alertsMock.createRuleExecutorServices(); const actionsClient = actionsClientMock.create(); - const rulesClient = rulesClientMock.create(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const savedObjectsService = savedObjectsServiceMock.createInternalStartContract(); const elasticsearchService = elasticsearchServiceMock.createInternalStart(); @@ -180,7 +183,6 @@ describe('Task Runner', () => { encryptedSavedObjectsClient, eventLogger: eventLoggerMock.create(), executionContext: executionContextServiceMock.createInternalStartContract(), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), kibanaBaseUrl: 'https://localhost:5601', logger, maintenanceWindowsService, @@ -232,7 +234,6 @@ describe('Task Runner', () => { }); savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( actionsClient ); @@ -286,7 +287,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); @@ -395,7 +396,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); expect(enqueueFunction).toHaveBeenCalledTimes(1); @@ -486,7 +487,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), muteAll: true, }); @@ -621,7 +622,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), muteAll, snoozeSchedule: snoozeSchedule != null ? JSON.parse(snoozeSchedule) : [], @@ -683,7 +684,7 @@ describe('Task Runner', () => { internalSavedObjectsRepository, }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -755,7 +756,7 @@ describe('Task Runner', () => { internalSavedObjectsRepository, }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -818,7 +819,7 @@ describe('Task Runner', () => { internalSavedObjectsRepository, }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -888,7 +889,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), mutedInstanceIds: ['2'], }); @@ -981,7 +982,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onThrottleInterval', throttle: '1d', @@ -1030,7 +1031,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), mutedInstanceIds: ['2'], notifyWhen: 'onActionGroupChange', @@ -1091,7 +1092,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', }); @@ -1162,7 +1163,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', }); @@ -1227,7 +1228,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); expect( @@ -1344,7 +1345,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult.state.alertInstances).toEqual( @@ -1483,7 +1484,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult.state.alertInstances).toEqual( @@ -1596,7 +1597,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), actions: [ { @@ -1685,7 +1686,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), actions: [ { @@ -1748,7 +1749,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), actions: [ { @@ -1839,7 +1840,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult.state.alertInstances).toEqual( @@ -1899,7 +1900,7 @@ describe('Task Runner', () => { inMemoryMetrics, }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -1942,7 +1943,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(mockedRawRuleSO); const runnerResult = await taskRunner.run(); @@ -2060,7 +2061,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); @@ -2127,7 +2128,7 @@ describe('Task Runner', () => { }); test('reschedules for smaller interval if es connectivity error encountered and schedule interval is greater than connectivity retry', async () => { - rulesClient.getAlertFromRaw.mockImplementation(() => { + mockGetAlertFromRaw.mockImplementation(() => { throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError( RULE_SAVED_OBJECT_TYPE, '1' @@ -2229,7 +2230,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], @@ -2340,7 +2341,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], @@ -2418,7 +2419,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], @@ -2490,7 +2491,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], @@ -2568,7 +2569,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], @@ -2621,7 +2622,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); @@ -2692,7 +2693,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); @@ -2709,7 +2710,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(mockedRawRuleSO); ruleType.executor.mockImplementation( async ({ @@ -2742,7 +2743,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); await taskRunner.run(); @@ -2782,7 +2783,7 @@ describe('Task Runner', () => { inMemoryMetrics, }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ ...mockedRawRuleSO, attributes: { ...mockedRawRuleSO.attributes, schedule: { interval: '50s' } }, @@ -2804,7 +2805,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); ruleType.executor.mockImplementation( @@ -2845,7 +2846,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); for (let i = 0; i < 300; i++) { @@ -2914,7 +2915,7 @@ describe('Task Runner', () => { }, ]; - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), actions: mockActions as RuleAction[], }); @@ -3054,7 +3055,7 @@ describe('Task Runner', () => { } ); - rulesClient.getAlertFromRaw.mockReturnValue({ + mockGetAlertFromRaw.mockReturnValue({ ...(mockedRuleTypeSavedObject as Rule), actions: [ { @@ -3189,7 +3190,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -3272,7 +3273,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult.state.alertInstances).toEqual({}); @@ -3299,7 +3300,7 @@ describe('Task Runner', () => { }); test('reports error to eventLogger when ruleResultService.addLastRunError adds an error', async () => { - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const taskRunner = new TaskRunner({ @@ -3343,7 +3344,7 @@ describe('Task Runner', () => { }); test('returns user error if all the errors reported by getLastRunResults are user error', async () => { - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const taskRunner = new TaskRunner({ @@ -3393,7 +3394,7 @@ describe('Task Runner', () => { context: taskRunnerFactoryInitializerParams, inMemoryMetrics, }); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(mockedRawRuleSO); const runnerResult = await taskRunner.run(); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index b5a1854581bf34..25dac75b5d7c34 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -66,7 +66,12 @@ import { RuleRunningHandler } from './rule_running_handler'; import { RuleResultService } from '../monitoring/rule_result_service'; import { RuleTypeRunner } from './rule_type_runner'; import { initializeAlertsClient } from '../alerts_client'; -import { createTaskRunnerLogger, withAlertingSpan, processRunResults } from './lib'; +import { + createTaskRunnerLogger, + withAlertingSpan, + processRunResults, + clearExpiredSnoozes, +} from './lib'; const FALLBACK_RETRY_INTERVAL = '5m'; const CONNECTIVITY_RETRY_INTERVAL = '5m'; @@ -503,6 +508,7 @@ export class TaskRunner< paramValidator: this.ruleType.validate.params, ruleId, spaceId, + logger: this.logger, context: this.context, ruleTypeRegistry: this.ruleTypeRegistry, }); @@ -522,7 +528,9 @@ export class TaskRunner< (async () => { try { - await runRuleParams.rulesClient.clearExpiredSnoozes({ + await clearExpiredSnoozes({ + esClient: this.context.elasticsearch.client.asInternalUser, + logger: this.logger, rule: runRuleParams.rule, version: runRuleParams.version, }); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts index 6c7331de463ea4..deaae7bccc479f 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_alerts_client.test.ts @@ -34,7 +34,7 @@ import { } from '@kbn/core/server/mocks'; import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; import { actionsMock, actionsClientMock } from '@kbn/actions-plugin/server/mocks'; -import { alertsMock, rulesClientMock } from '../mocks'; +import { alertsMock } from '../mocks'; import { eventLoggerMock } from '@kbn/event-log-plugin/server/event_logger.mock'; import { IEventLogger } from '@kbn/event-log-plugin/server'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; @@ -52,6 +52,7 @@ import { DATE_1970_5_MIN, mockedRawRuleSO, } from './fixtures'; +import { getAlertFromRaw } from '../rules_client/lib/get_alert_from_raw'; import { dataPluginMock } from '@kbn/data-plugin/server/mocks'; import { AlertingEventLogger } from '../lib/alerting_event_logger/alerting_event_logger'; import { alertingEventLoggerMock } from '../lib/alerting_event_logger/alerting_event_logger.mock'; @@ -118,6 +119,9 @@ jest.mock('../lib/wrap_scoped_cluster_client', () => ({ jest.mock('../lib/alerting_event_logger/alerting_event_logger'); +jest.mock('../rules_client/lib/get_alert_from_raw'); +const mockGetAlertFromRaw = getAlertFromRaw as jest.MockedFunction; + let fakeTimer: sinon.SinonFakeTimers; const logger: ReturnType = loggingSystemMock.createLogger(); const taskRunnerLogger = createTaskRunnerLogger({ logger, tags: ['1', 'test'] }); @@ -167,7 +171,6 @@ describe('Task Runner', () => { const services = alertsMock.createRuleExecutorServices(); const actionsClient = actionsClientMock.create(); const rulesSettingsService = rulesSettingsServiceMock.create(); - const rulesClient = rulesClientMock.create(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const savedObjectsService = savedObjectsServiceMock.createInternalStartContract(); const elasticsearchService = elasticsearchServiceMock.createInternalStart(); @@ -207,7 +210,6 @@ describe('Task Runner', () => { encryptedSavedObjectsClient, eventLogger: eventLoggerMock.create(), executionContext: executionContextServiceMock.createInternalStartContract(), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), kibanaBaseUrl: 'https://localhost:5601', logger, maintenanceWindowsService, @@ -238,7 +240,6 @@ describe('Task Runner', () => { }); savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( actionsClient ); @@ -321,7 +322,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -433,7 +434,7 @@ describe('Task Runner', () => { inMemoryMetrics, }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); @@ -579,7 +580,7 @@ describe('Task Runner', () => { inMemoryMetrics, }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -677,7 +678,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); @@ -771,7 +772,7 @@ describe('Task Runner', () => { }); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); await taskRunner.run(); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index e5572707ae6fde..c96a3f95c636e4 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -32,12 +32,13 @@ import { } from '@kbn/core/server/mocks'; import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; import { actionsMock, actionsClientMock } from '@kbn/actions-plugin/server/mocks'; -import { alertsMock, rulesClientMock } from '../mocks'; +import { alertsMock } from '../mocks'; import { eventLoggerMock } from '@kbn/event-log-plugin/server/event_logger.mock'; import { IEventLogger } from '@kbn/event-log-plugin/server'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { dataPluginMock } from '@kbn/data-plugin/server/mocks'; import { inMemoryMetricsMock } from '../monitoring/in_memory_metrics.mock'; +import { getAlertFromRaw } from '../rules_client/lib/get_alert_from_raw'; import { AlertingEventLogger, ContextOpts, @@ -75,6 +76,9 @@ jest.mock('../lib/wrap_scoped_cluster_client', () => ({ jest.mock('../lib/alerting_event_logger/alerting_event_logger'); +jest.mock('../rules_client/lib/get_alert_from_raw'); +const mockGetAlertFromRaw = getAlertFromRaw as jest.MockedFunction; + let fakeTimer: sinon.SinonFakeTimers; const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); @@ -112,7 +116,6 @@ describe('Task Runner Cancel', () => { const internalSavedObjectsRepository = savedObjectsRepositoryMock.create(); const backfillClient = backfillClientMock.create(); const actionsClient = actionsClientMock.create(); - const rulesClient = rulesClientMock.create(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const savedObjectsService = savedObjectsServiceMock.createInternalStartContract(); const elasticsearchService = elasticsearchServiceMock.createInternalStart(); @@ -142,7 +145,6 @@ describe('Task Runner Cancel', () => { encryptedSavedObjectsClient, eventLogger: eventLoggerMock.create(), executionContext: executionContextServiceMock.createInternalStartContract(), - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), kibanaBaseUrl: 'https://localhost:5601', logger, maintenanceWindowsService, @@ -172,7 +174,6 @@ describe('Task Runner Cancel', () => { }); savedObjectsService.getScopedClient.mockReturnValue(services.savedObjectsClient); elasticsearchService.client.asScoped.mockReturnValue(services.scopedClusterClient); - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockReturnValue(rulesClient); taskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mockResolvedValue( actionsClient ); @@ -187,7 +188,7 @@ describe('Task Runner Cancel', () => { flappingSettings: DEFAULT_FLAPPING_SETTINGS, queryDelaySettings: DEFAULT_QUERY_DELAY_SETTINGS, }); - rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + mockGetAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); maintenanceWindowsService.getMaintenanceWindows.mockReturnValue({ maintenanceWindows: [], maintenanceWindowsWithoutScopedQueryIds: [], diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts index 855e8ee2050f84..ed4b5a0802232c 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.test.ts @@ -18,7 +18,6 @@ import { uiSettingsServiceMock, } from '@kbn/core/server/mocks'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; -import { rulesClientMock } from '../mocks'; import { eventLoggerMock } from '@kbn/event-log-plugin/server/event_logger.mock'; import { UntypedNormalizedRuleType } from '../rule_type_registry'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; @@ -101,7 +100,6 @@ describe('Task Runner Factory', () => { afterAll(() => fakeTimer.restore()); const encryptedSavedObjectsPlugin = encryptedSavedObjectsMock.createStart(); - const rulesClient = rulesClientMock.create(); const connectorAdapterRegistry = new ConnectorAdapterRegistry(); const taskRunnerFactoryInitializerParams: jest.Mocked = { @@ -118,7 +116,6 @@ describe('Task Runner Factory', () => { encryptedSavedObjectsClient: encryptedSavedObjectsPlugin.getClient(), eventLogger: eventLoggerMock.create(), executionContext, - getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), kibanaBaseUrl: 'https://localhost:5601', logger: loggingSystemMock.create().get(), maintenanceWindowsService, diff --git a/x-pack/plugins/alerting/server/task_runner/types.ts b/x-pack/plugins/alerting/server/task_runner/types.ts index 8598987e12f9dd..a92ee2a89d654e 100644 --- a/x-pack/plugins/alerting/server/task_runner/types.ts +++ b/x-pack/plugins/alerting/server/task_runner/types.ts @@ -46,7 +46,6 @@ import { NormalizedRuleType } from '../rule_type_registry'; import { CombinedSummarizedAlerts, RawRule, - RulesClientApi, RuleTypeRegistry, SpaceIdToNamespaceFunction, } from '../types'; @@ -74,7 +73,6 @@ export interface RunRuleParams { apiKey: RawRule['apiKey']; fakeRequest: KibanaRequest; rule: SanitizedRule; - rulesClient: RulesClientApi; validatedParams: Params; version: string | undefined; } @@ -169,7 +167,6 @@ export interface TaskRunnerContext { encryptedSavedObjectsClient: EncryptedSavedObjectsClient; eventLogger: IEventLogger; executionContext: ExecutionContextStart; - getRulesClientWithRequest(request: KibanaRequest): RulesClientApi; kibanaBaseUrl: string | undefined; logger: Logger; maintenanceWindowsService: MaintenanceWindowsService;