[ResponseOps][Alerting] Hiding all features in a space causes rules to stop running (#146188)

Resolves https://github.com/elastic/kibana/issues/144638
## Summary

Removes logic that prevents rules from running when all features in a
space are disabled.

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

### To verify
- Create an alerting rule
- Go to the [spaces
page](http://localhost:5601/app/management/kibana/spaces), and disable
all features in the space
- Look at your terminal to see the alerting rule still running and no
errors

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Alexi Doak 2022-12-12 14:22:08 -05:00 committed by GitHub
parent b80a23ee12
commit 4f1552e338
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 165 additions and 125 deletions

View file

@ -45,6 +45,7 @@ const createRulesClientMock = () => {
clearExpiredSnoozes: jest.fn(),
runSoon: jest.fn(),
clone: jest.fn(),
getAlertFromRaw: jest.fn(),
};
return mocked;
};

View file

@ -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<Params extends RuleTypeParams>(
context: RulesClientContext,
id: string,

View file

@ -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
);
}

View file

@ -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;
}
}

View file

@ -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 extends RuleTypeParams>(params: LoadRulePa
params;
let enabled: boolean;
let apiKey: string | null;
let rule: SanitizedRule<Params>;
let fakeRequest: CoreKibanaRequest;
let rulesClient: RulesClientApi;
try {
const decryptedAttributes = await getDecryptedAttributes(context, ruleId, spaceId);
apiKey = decryptedAttributes.apiKey;
enabled = decryptedAttributes.enabled;
const attributes = await getRuleAttributes<Params>(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 extends RuleTypeParams>(params: LoadRulePa
);
}
const fakeRequest = getFakeKibanaRequest(context, spaceId, apiKey);
const rulesClient = context.getRulesClientWithRequest(fakeRequest);
let rule: SanitizedRule<Params>;
// Ensure API key is still valid and user has access
try {
rule = await rulesClient.get<Params>({ id: ruleId });
} catch (err) {
throw new ErrorWithReason(RuleExecutionStatusErrorReasons.Read, err);
}
alertingEventLogger.setRuleName(rule.name);
try {
@ -94,24 +89,44 @@ export async function loadRule<Params extends RuleTypeParams>(params: LoadRulePa
};
}
export async function getDecryptedAttributes(
export async function getRuleAttributes<Params extends RuleTypeParams>(
context: TaskRunnerContext,
ruleId: string,
spaceId: string
): Promise<{ apiKey: string | null; enabled: boolean; consumer: string }> {
): Promise<{
apiKey: string | null;
enabled: boolean;
consumer: string;
rule: SanitizedRule<Params>;
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<RawRule>(
const rawRule = await context.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>(
'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(

View file

@ -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<unknown>);
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<unknown>);
] 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',

View file

@ -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<Params>({
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);

View file

@ -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: {