diff --git a/x-pack/plugins/alerting/server/rules_client.mock.ts b/x-pack/plugins/alerting/server/rules_client.mock.ts index e9c3c3a0cee73..cef3381600fa1 100644 --- a/x-pack/plugins/alerting/server/rules_client.mock.ts +++ b/x-pack/plugins/alerting/server/rules_client.mock.ts @@ -45,6 +45,7 @@ const createRulesClientMock = () => { clearExpiredSnoozes: jest.fn(), runSoon: jest.fn(), clone: jest.fn(), + getAlertFromRaw: jest.fn(), }; return mocked; }; 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 72cd5c0ec4b1a..849442f4556e3 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 @@ -26,6 +26,16 @@ import { } from '../common'; import { RulesClientContext } from '../types'; +export interface GetAlertFromRawParams { + id: string; + ruleTypeId: string; + rawRule: RawRule; + references: SavedObjectReference[] | undefined; + includeLegacyId?: boolean; + excludeFromPublicApi?: boolean; + includeSnoozeData?: boolean; +} + export function getAlertFromRaw( context: RulesClientContext, id: string, 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 d790ec3587d77..35cb052ac6381 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -52,6 +52,7 @@ import { muteInstance } from './methods/mute_instance'; import { unmuteInstance } from './methods/unmute_instance'; import { runSoon } from './methods/run_soon'; import { listAlertTypes } from './methods/list_alert_types'; +import { getAlertFromRaw, GetAlertFromRawParams } from './lib/get_alert_from_raw'; export type ConstructorOptions = Omit< RulesClientContext, @@ -135,4 +136,16 @@ export class RulesClient { public getSpaceId(): string | undefined { return this.context.spaceId; } + + public getAlertFromRaw = (params: GetAlertFromRawParams) => + getAlertFromRaw( + this.context, + params.id, + params.ruleTypeId, + params.rawRule, + params.references, + params.includeLegacyId, + params.excludeFromPublicApi, + params.includeSnoozeData + ); } 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 1cbe2bb2ae3b9..efc9d0418ccd2 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 @@ -9,11 +9,11 @@ import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/s import { CoreKibanaRequest } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; -import { getDecryptedAttributes, getFakeKibanaRequest, loadRule } from './rule_loader'; +import { getRuleAttributes, getFakeKibanaRequest, loadRule } from './rule_loader'; import { TaskRunnerContext } from './task_runner_factory'; import { ruleTypeRegistryMock } from '../rule_type_registry.mock'; import { rulesClientMock } from '../rules_client.mock'; -import { Rule, RulesClientApi } from '../types'; +import { Rule } from '../types'; import { MONITORING_HISTORY_LIMIT, RuleExecutionStatusErrorReasons } from '../../common'; import { getReasonFromError } from '../lib/error_with_reason'; import { alertingEventLoggerMock } from '../lib/alerting_event_logger/alerting_event_logger.mock'; @@ -137,25 +137,6 @@ describe('rule_loader', () => { expect(outcome).toBe('failure'); }); - test('throws when user cannot read rule', async () => { - context.getRulesClientWithRequest = function (fakeRequest: unknown): RulesClientApi { - rulesClient.get.mockImplementation(async (args: unknown) => { - throw new Error('rule-client-error: 1001'); - }); - return rulesClient; - }; - - let outcome = 'success'; - try { - await loadRule({ ...DefaultLoadRuleParams, context }); - } catch (err) { - outcome = 'failure'; - expect(err.message).toBe('rule-client-error: 1001'); - expect(getReasonFromError(err)).toBe(RuleExecutionStatusErrorReasons.Read); - } - expect(outcome).toBe('failure'); - }); - test('throws when rule type is not enabled', async () => { ruleTypeRegistry.ensureRuleTypeEnabled.mockImplementation(() => { throw new Error('rule-type-not-enabled: 2112'); @@ -196,11 +177,14 @@ describe('rule_loader', () => { describe('getDecryptedAttributes()', () => { test('succeeds with default space', async () => { contextMock.spaceIdToNamespace.mockReturnValue(undefined); - const result = await getDecryptedAttributes(context, ruleId, 'default'); + const result = await getRuleAttributes(context, ruleId, 'default'); expect(result.apiKey).toBe(apiKey); expect(result.consumer).toBe(consumer); expect(result.enabled).toBe(true); + expect(result.fakeRequest).toEqual(expect.any(CoreKibanaRequest)); + expect(result.rule.alertTypeId).toBe(ruleTypeId); + expect(result.rulesClient).toBeTruthy(); expect(contextMock.spaceIdToNamespace.mock.calls[0]).toEqual(['default']); const esoArgs = encryptedSavedObjects.getDecryptedAsInternalUser.mock.calls[0]; @@ -209,11 +193,14 @@ describe('rule_loader', () => { test('succeeds with non-default space', async () => { contextMock.spaceIdToNamespace.mockReturnValue(spaceId); - const result = await getDecryptedAttributes(context, ruleId, spaceId); + const result = await getRuleAttributes(context, ruleId, spaceId); expect(result.apiKey).toBe(apiKey); expect(result.consumer).toBe(consumer); expect(result.enabled).toBe(true); + expect(result.fakeRequest).toEqual(expect.any(CoreKibanaRequest)); + expect(result.rule.alertTypeId).toBe(ruleTypeId); + expect(result.rulesClient).toBeTruthy(); expect(contextMock.spaceIdToNamespace.mock.calls[0]).toEqual([spaceId]); const esoArgs = encryptedSavedObjects.getDecryptedAsInternalUser.mock.calls[0]; @@ -227,7 +214,7 @@ describe('rule_loader', () => { } ); - const promise = getDecryptedAttributes(context, ruleId, spaceId); + const promise = getRuleAttributes(context, ruleId, spaceId); await expect(promise).rejects.toThrow('wops'); }); }); @@ -340,20 +327,18 @@ function getTaskRunnerContext(ruleParameters: unknown, historyElements: number) getRulesClientWithRequest, }; - function getRulesClientWithRequest(fakeRequest: unknown) { + function getRulesClientWithRequest() { // only need get() mocked - rulesClient.get.mockImplementation(async (args: unknown) => { - return { - name: ruleName, - alertTypeId: ruleTypeId, - params: ruleParameters, - monitoring: { - run: { - history: new Array(historyElements), - }, + rulesClient.getAlertFromRaw.mockReturnValue({ + name: ruleName, + alertTypeId: ruleTypeId, + params: ruleParameters, + monitoring: { + run: { + history: new Array(historyElements), }, - } as Rule; - }); + }, + } 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 8d4b00a54e094..f1af95ff2c7a4 100644 --- a/x-pack/plugins/alerting/server/task_runner/rule_loader.ts +++ b/x-pack/plugins/alerting/server/task_runner/rule_loader.ts @@ -17,6 +17,7 @@ import { RuleTypeRegistry, RuleTypeParamsValidator, SanitizedRule, + RulesClientApi, } from '../types'; import { MONITORING_HISTORY_LIMIT, RuleTypeParams } from '../../common'; import { AlertingEventLogger } from '../lib/alerting_event_logger/alerting_event_logger'; @@ -35,11 +36,17 @@ export async function loadRule(params: LoadRulePa params; let enabled: boolean; let apiKey: string | null; + let rule: SanitizedRule; + let fakeRequest: CoreKibanaRequest; + let rulesClient: RulesClientApi; try { - const decryptedAttributes = await getDecryptedAttributes(context, ruleId, spaceId); - apiKey = decryptedAttributes.apiKey; - enabled = decryptedAttributes.enabled; + const attributes = await getRuleAttributes(context, ruleId, spaceId); + apiKey = attributes.apiKey; + enabled = attributes.enabled; + rule = attributes.rule; + fakeRequest = attributes.fakeRequest; + rulesClient = attributes.rulesClient; } catch (err) { throw new ErrorWithReason(RuleExecutionStatusErrorReasons.Decrypt, err); } @@ -51,18 +58,6 @@ export async function loadRule(params: LoadRulePa ); } - const fakeRequest = getFakeKibanaRequest(context, spaceId, apiKey); - const rulesClient = context.getRulesClientWithRequest(fakeRequest); - - let rule: SanitizedRule; - - // Ensure API key is still valid and user has access - try { - rule = await rulesClient.get({ id: ruleId }); - } catch (err) { - throw new ErrorWithReason(RuleExecutionStatusErrorReasons.Read, err); - } - alertingEventLogger.setRuleName(rule.name); try { @@ -94,24 +89,44 @@ export async function loadRule(params: LoadRulePa }; } -export async function getDecryptedAttributes( +export async function getRuleAttributes( context: TaskRunnerContext, ruleId: string, spaceId: string -): Promise<{ apiKey: string | null; enabled: boolean; consumer: string }> { +): Promise<{ + apiKey: string | null; + enabled: boolean; + consumer: string; + rule: SanitizedRule; + fakeRequest: CoreKibanaRequest; + rulesClient: RulesClientApi; +}> { const namespace = context.spaceIdToNamespace(spaceId); - // Only fetch encrypted attributes here, we'll create a saved objects client - // scoped with the API key to fetch the remaining data. - const { - attributes: { apiKey, enabled, consumer }, - } = await context.encryptedSavedObjectsClient.getDecryptedAsInternalUser( + const rawRule = await context.encryptedSavedObjectsClient.getDecryptedAsInternalUser( 'alert', ruleId, { namespace } ); - return { apiKey, enabled, consumer }; + const fakeRequest = getFakeKibanaRequest(context, spaceId, rawRule.attributes.apiKey); + const rulesClient = context.getRulesClientWithRequest(fakeRequest); + const rule = rulesClient.getAlertFromRaw({ + id: ruleId, + ruleTypeId: rawRule.attributes.alertTypeId as string, + rawRule: rawRule.attributes as RawRule, + references: rawRule.references, + includeLegacyId: false, + }); + + return { + rule, + apiKey: rawRule.attributes.apiKey, + enabled: rawRule.attributes.enabled, + consumer: rawRule.attributes.consumer, + fakeRequest, + rulesClient, + }; } export function getFakeKibanaRequest( 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 c42a69fb33716..b07f29f07caf2 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 @@ -14,6 +14,8 @@ import { AlertInstanceState, AlertInstanceContext, RuleExecutionStatusWarningReasons, + Rule, + RuleAction, } from '../types'; import { ConcreteTaskInstance, isUnrecoverableError } from '@kbn/task-manager-plugin/server'; import { TaskRunnerContext } from './task_runner_factory'; @@ -220,7 +222,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); @@ -320,7 +322,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); await taskRunner.run(); expect(enqueueFunction).toHaveBeenCalledTimes(1); @@ -402,8 +404,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), muteAll: true, }); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); @@ -527,8 +529,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), muteAll, snoozeSchedule: snoozeSchedule != null ? JSON.parse(snoozeSchedule) : [], }); @@ -580,8 +582,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), mutedInstanceIds: ['2'], }); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); @@ -663,8 +665,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onThrottleInterval', throttle: '1d', }); @@ -708,8 +710,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), mutedInstanceIds: ['2'], notifyWhen: 'onActionGroupChange', }); @@ -765,8 +767,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', }); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); @@ -833,8 +835,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalledTimes(1); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', }); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); @@ -895,8 +897,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); await taskRunner.run(); expect( customTaskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest @@ -1009,7 +1011,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); expect(runnerResult.state.alertInstances).toEqual( @@ -1138,7 +1140,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); expect(runnerResult.state.alertInstances).toEqual( @@ -1243,8 +1245,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), actions: [ { group: 'default', @@ -1346,7 +1348,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); expect(runnerResult.state.alertInstances).toEqual( @@ -1401,13 +1403,11 @@ describe('Task Runner', () => { inMemoryMetrics ); expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValueOnce(mockedRuleTypeSavedObject); - rulesClient.get.mockResolvedValueOnce({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), schedule: { interval: '30s' }, }); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual( @@ -1439,7 +1439,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); const runnerResult = await taskRunner.run(); @@ -1467,7 +1467,7 @@ describe('Task Runner', () => { test('recovers gracefully when the Alert Task Runner throws an exception when loading rule to prepare for run', async () => { // used in loadRule() which is called in prepareToRun() - rulesClient.get.mockImplementation(() => { + rulesClient.getAlertFromRaw.mockImplementation(() => { throw new Error(GENERIC_ERROR_MESSAGE); }); @@ -1488,7 +1488,7 @@ describe('Task Runner', () => { testAlertingEventLogCalls({ setRuleName: false, status: 'error', - errorReason: 'read', + errorReason: 'decrypt', executionStatus: 'not-reached', }); @@ -1550,7 +1550,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); @@ -1624,7 +1624,7 @@ describe('Task Runner', () => { }); test('reschedules for smaller interval if es connectivity error encountered and schedule interval is greater than connectivity retry', async () => { - rulesClient.get.mockImplementation(() => { + rulesClient.getAlertFromRaw.mockImplementation(() => { throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('alert', '1'); }); @@ -1721,11 +1721,12 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], }); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); await taskRunner.run(); @@ -1827,11 +1828,12 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], }); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); await taskRunner.run(); @@ -1901,8 +1903,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], }); @@ -1970,8 +1972,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], }); @@ -2044,8 +2046,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), notifyWhen: 'onActionGroupChange', actions: [], }); @@ -2096,7 +2098,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); @@ -2161,8 +2163,8 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual(generateRunnerResult({ state: true, history: [true] })); }); @@ -2176,7 +2178,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); ruleType.executor.mockImplementation( async ({ @@ -2204,7 +2206,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); await taskRunner.run(); await taskRunner.run(); @@ -2238,11 +2240,11 @@ describe('Task Runner', () => { inMemoryMetrics ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), schedule: { interval: '50s' }, }); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); await taskRunner.run(); expect( @@ -2263,7 +2265,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); ruleType.executor.mockImplementation( @@ -2311,7 +2313,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); for (let i = 0; i < 300; i++) { @@ -2378,12 +2380,13 @@ describe('Task Runner', () => { }, ]; - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, - actions: mockActions, - } as jest.ResolvedValue); + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), + actions: mockActions as RuleAction[], + }); + ruleTypeRegistry.get.mockReturnValue(ruleType); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); const taskRunner = new TaskRunner( ruleType, @@ -2514,8 +2517,8 @@ describe('Task Runner', () => { } ); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, + rulesClient.getAlertFromRaw.mockReturnValue({ + ...(mockedRuleTypeSavedObject as Rule), actions: [ { group: 'default', @@ -2542,8 +2545,8 @@ describe('Task Runner', () => { id: '5', actionTypeId: 'any-action', }, - ], - } as jest.ResolvedValue); + ] as RuleAction[], + }); ruleTypeRegistry.get.mockReturnValue(ruleType); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); @@ -2643,7 +2646,7 @@ describe('Task Runner', () => { ); expect(AlertingEventLogger).toHaveBeenCalled(); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ id: '1', type: 'alert', 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 9e0d75a6a3795..5c4a0fc4f4996 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -671,7 +671,18 @@ export class TaskRunner< // fetch the rule again to ensure we return the correct schedule as it may have // changed during the task execution - schedule = asOk((await preparedResult.rulesClient.get({ id: ruleId })).schedule); + schedule = asOk( + ( + await loadRule({ + paramValidator: this.ruleType.validate?.params, + ruleId, + spaceId, + context: this.context, + ruleTypeRegistry: this.ruleTypeRegistry, + alertingEventLogger: this.alertingEventLogger, + }) + ).rule.schedule + ); } catch (err) { stateWithMetrics = asErr(err); schedule = asErr(err); 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 33efc649add26..ebfff148a7016 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 @@ -13,6 +13,7 @@ import { RuleTypeState, AlertInstanceState, AlertInstanceContext, + Rule, } from '../types'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; import { TaskRunnerContext } from './task_runner_factory'; @@ -156,8 +157,9 @@ describe('Task Runner Cancel', () => { taskRunnerFactoryInitializerParams.executionContext.withContext.mockImplementation((ctx, fn) => fn() ); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ + rulesClient.getAlertFromRaw.mockReturnValue(mockedRuleTypeSavedObject as Rule); + + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ id: '1', type: 'alert', attributes: {