diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_delete/bulk_delete_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_delete/bulk_delete_rules.test.ts index 3153a32e47852..40ac0e02a3d8e 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_delete/bulk_delete_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_delete/bulk_delete_rules.test.ts @@ -24,9 +24,9 @@ import { enabledRuleForBulkOps1, enabledRuleForBulkOps2, enabledRuleForBulkOps3, - returnedRuleForBulkDelete1, - returnedRuleForBulkDelete2, - returnedRuleForBulkDelete3, + returnedRuleForBulkOps1, + returnedRuleForBulkOps2, + returnedRuleForBulkOps3, siemRuleForBulkOps1, } from '../../../../rules_client/tests/test_helpers'; import { migrateLegacyActions } from '../../../../rules_client/lib'; @@ -81,6 +81,7 @@ const rulesClientParams: jest.Mocked = { isAuthenticationTypeAPIKey: jest.fn(), getAuthenticationAPIKey: jest.fn(), connectorAdapterRegistry: new ConnectorAdapterRegistry(), + isSystemAction: jest.fn(), getAlertIndicesAlias: jest.fn(), alertsService: null, }; @@ -192,7 +193,7 @@ describe('bulkDelete', () => { expect.anything() ); expect(result).toStrictEqual({ - rules: [returnedRuleForBulkDelete1, returnedRuleForBulkDelete3], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps3], errors: [{ message: 'UPS', rule: { id: 'id2', name: 'fakeName' }, status: 500 }], total: 2, taskIdsFailedToBeDeleted: [], @@ -256,7 +257,7 @@ describe('bulkDelete', () => { expect.anything() ); expect(result).toStrictEqual({ - rules: [returnedRuleForBulkDelete1], + rules: [returnedRuleForBulkOps1], errors: [{ message: 'UPS', rule: { id: 'id2', name: 'fakeName' }, status: 409 }], total: 2, taskIdsFailedToBeDeleted: [], @@ -314,7 +315,7 @@ describe('bulkDelete', () => { expect.anything() ); expect(result).toStrictEqual({ - rules: [returnedRuleForBulkDelete1, returnedRuleForBulkDelete2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], errors: [], total: 2, taskIdsFailedToBeDeleted: [], diff --git a/x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts b/x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts index 239422d5ad28a..ffa4454bd1f04 100644 --- a/x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts +++ b/x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts @@ -41,12 +41,12 @@ export interface RRuleAttributes { byweekday?: Array; bymonth?: number[]; bysetpos?: number[]; - bymonthday: number[]; - byyearday: number[]; - byweekno: number[]; - byhour: number[]; - byminute: number[]; - bysecond: number[]; + bymonthday?: number[]; + byyearday?: number[]; + byweekno?: number[]; + byhour?: number[]; + byminute?: number[]; + bysecond?: number[]; } export interface RuleSnoozeScheduleAttributes { diff --git a/x-pack/plugins/alerting/server/routes/bulk_enable_rules.test.ts b/x-pack/plugins/alerting/server/routes/bulk_enable_rules.test.ts index 367eb0c75ba96..51a060388d3e6 100644 --- a/x-pack/plugins/alerting/server/routes/bulk_enable_rules.test.ts +++ b/x-pack/plugins/alerting/server/routes/bulk_enable_rules.test.ts @@ -6,13 +6,14 @@ */ import { httpServiceMock } from '@kbn/core/server/mocks'; - +import { actionsClientMock } from '@kbn/actions-plugin/server/mocks'; import { bulkEnableRulesRoute } from './bulk_enable_rules'; import { licenseStateMock } from '../lib/license_state.mock'; import { mockHandlerArguments } from './_mock_handler_arguments'; import { rulesClientMock } from '../rules_client.mock'; import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled'; import { verifyApiAccess } from '../lib/license_api_access'; +import { RuleActionTypes, RuleDefaultAction, RuleSystemAction, SanitizedRule } from '../types'; const rulesClient = rulesClientMock.create(); @@ -123,4 +124,121 @@ describe('bulkEnableRulesRoute', () => { expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); }); + + describe('actions', () => { + const mockedRule: SanitizedRule<{}> = { + id: '1', + alertTypeId: '1', + schedule: { interval: '10s' }, + params: { + bar: true, + }, + createdAt: new Date(), + updatedAt: new Date(), + actions: [ + { + group: 'default', + id: '2', + actionTypeId: 'test', + params: { + foo: true, + }, + uuid: '123-456', + type: RuleActionTypes.DEFAULT, + }, + ], + consumer: 'bar', + name: 'abc', + tags: ['foo'], + enabled: true, + muteAll: false, + notifyWhen: 'onActionGroupChange', + createdBy: '', + updatedBy: '', + apiKeyOwner: '', + throttle: '30s', + mutedInstanceIds: [], + executionStatus: { + status: 'unknown', + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + }, + revision: 0, + }; + + const action: RuleDefaultAction = { + actionTypeId: 'test', + group: 'default', + id: '2', + params: { + foo: true, + }, + uuid: '123-456', + type: RuleActionTypes.DEFAULT, + }; + + const systemAction: RuleSystemAction = { + actionTypeId: 'test-2', + id: 'system_action-id', + params: { + foo: true, + }, + uuid: '123-456', + type: RuleActionTypes.SYSTEM, + }; + + const mockedRules: Array> = [ + { ...mockedRule, actions: [action, systemAction] }, + ]; + + const bulkEnableActionsResult = { + rules: mockedRules, + errors: [], + total: 1, + taskIdsFailedToBeEnabled: [], + }; + + it('removes the type from the actions correctly before sending the response', async () => { + const licenseState = licenseStateMock.create(); + const router = httpServiceMock.createRouter(); + const actionsClient = actionsClientMock.create(); + actionsClient.isSystemAction.mockImplementation((id: string) => id === 'system_action-id'); + + bulkEnableRulesRoute({ router, licenseState }); + const [_, handler] = router.patch.mock.calls[0]; + + // rulesClient.bulkDisableRules.mockResolvedValueOnce(bulkDisableActionsResult); + rulesClient.bulkEnableRules.mockResolvedValueOnce(bulkEnableActionsResult); + + const [context, req, res] = mockHandlerArguments( + { rulesClient, actionsClient }, + { + body: bulkEnableRequest, + }, + ['ok'] + ); + + const routeRes = await handler(context, req, res); + + // @ts-expect-error: body exists + expect(routeRes.body.rules[0].actions).toEqual([ + { + connector_type_id: 'test', + group: 'default', + id: '2', + params: { + foo: true, + }, + uuid: '123-456', + }, + { + connector_type_id: 'test-2', + id: 'system_action-id', + params: { + foo: true, + }, + uuid: '123-456', + }, + ]); + }); + }); }); diff --git a/x-pack/plugins/alerting/server/routes/bulk_enable_rules.ts b/x-pack/plugins/alerting/server/routes/bulk_enable_rules.ts index 50b35c3b16cb3..da9e9390938aa 100644 --- a/x-pack/plugins/alerting/server/routes/bulk_enable_rules.ts +++ b/x-pack/plugins/alerting/server/routes/bulk_enable_rules.ts @@ -10,6 +10,8 @@ import { IRouter } from '@kbn/core/server'; import { verifyAccessAndContext, handleDisabledApiKeysError } from './lib'; import { ILicenseState, RuleTypeDisabledError } from '../lib'; import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; +import { transformRuleToRuleResponseV1 } from './rule/transforms'; +import { Rule } from '../application/rule/types'; export const bulkEnableRulesRoute = ({ router, @@ -35,8 +37,20 @@ export const bulkEnableRulesRoute = ({ const { filter, ids } = req.body; try { - const result = await rulesClient.bulkEnableRules({ filter, ids }); - return res.ok({ body: result }); + const bulkEnableResults = await rulesClient.bulkEnableRules({ filter, ids }); + + const resultBody = { + body: { + ...bulkEnableResults, + rules: bulkEnableResults.rules.map((rule) => { + // TODO (http-versioning): Remove this cast, this enables us to move forward + // without fixing all of other solution types + return transformRuleToRuleResponseV1(rule as Rule); + }), + }, + }; + + return res.ok(resultBody); } catch (e) { if (e instanceof RuleTypeDisabledError) { return e.sendResponse(res); diff --git a/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts b/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts index cac39ccb367d4..eb139f168e88c 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts @@ -23,7 +23,6 @@ import { getRuleCircuitBreakerErrorMessage } from '../../../common'; import { getAuthorizationFilter, checkAuthorizationAndGetTotal, - getAlertFromRaw, scheduleTask, updateMeta, createNewAPIKeySet, @@ -32,6 +31,12 @@ import { import { RulesClientContext, BulkOperationError, BulkOptions } from '../types'; import { validateScheduleLimit } from '../../application/rule/methods/get_schedule_frequency'; import { RuleAttributes } from '../../data/rule/types'; +import { + transformRuleAttributesToRuleDomain, + transformRuleDomainToRule, +} from '../../application/rule/transforms'; +import type { RuleParams } from '../../application/rule/types'; +import { ruleDomainSchema } from '../../application/rule/schemas'; const getShouldScheduleTask = async ( context: RulesClientContext, @@ -57,8 +62,12 @@ const getShouldScheduleTask = async ( } }; -export const bulkEnableRules = async (context: RulesClientContext, options: BulkOptions) => { +export const bulkEnableRules = async ( + context: RulesClientContext, + options: BulkOptions +) => { const { ids, filter } = getAndValidateCommonBulkOptions(options); + const actionsClient = await context.getActionsClient(); const kueryNodeFilter = ids ? convertRuleIdsToKueryNode(ids) : buildKueryNodeFilter(filter); const authorizationFilter = await getAuthorizationFilter(context, { action: 'ENABLE' }); @@ -89,18 +98,32 @@ export const bulkEnableRules = async (context: RulesClientContext, options: Bulk taskManager: context.taskManager, }); - const updatedRules = rules.map(({ id, attributes, references }) => { - return getAlertFromRaw( - context, - id, - attributes.alertTypeId as string, - attributes as RawRule, - references, - false + const enabledRules = rules.map(({ id, attributes, references }) => { + // TODO (http-versioning): alertTypeId should never be null, but we need to + // fix the type cast from SavedObjectsBulkUpdateObject to SavedObjectsBulkUpdateObject + // when we are doing the bulk disable and this should fix itself + const ruleType = context.ruleTypeRegistry.get(attributes.alertTypeId!); + const ruleDomain = transformRuleAttributesToRuleDomain( + attributes as RuleAttributes, + { + id, + logger: context.logger, + ruleType, + references, + omitGeneratedValues: false, + }, + (connectorId: string) => actionsClient.isSystemAction(connectorId) ); + + try { + ruleDomainSchema.validate(ruleDomain); + } catch (e) { + context.logger.warn(`Error validating bulk enabled rule domain object for id: ${id}, ${e}`); + } + return transformRuleDomainToRule(ruleDomain); }); - return { errors, rules: updatedRules, total, taskIdsFailedToBeEnabled }; + return { errors, rules: enabledRules, total, taskIdsFailedToBeEnabled }; }; const bulkEnableRulesWithOCC = async ( diff --git a/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts index 0d96c85a18981..16fe7dba40748 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts @@ -18,19 +18,25 @@ import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { getBeforeSetup, setGlobalDate } from './lib'; import { loggerMock } from '@kbn/logging-mocks'; import { BulkUpdateTaskResult } from '@kbn/task-manager-plugin/server/task_scheduling'; +import { ActionsClient } from '@kbn/actions-plugin/server'; import { disabledRule1, disabledRule2, disabledRuleWithAction1, disabledRuleWithAction2, - enabledRule1, - enabledRule2, savedObjectWith409Error, savedObjectWith500Error, - returnedRule1, - returnedRule2, - siemRule1, - siemRule2, + enabledRuleForBulkOpsWithActions1, + enabledRuleForBulkOpsWithActions2, + returnedRuleForBulkEnableWithActions1, + returnedRuleForBulkEnableWithActions2, + enabledRuleForBulkOps1, + enabledRuleForBulkOps2, + returnedRuleForBulkOps1, + returnedRuleForBulkOps2, + disabledRuleForBulkDisable1, + siemRuleForBulkOps1, + siemRuleForBulkOps2, } from './test_helpers'; import { TaskStatus } from '@kbn/task-manager-plugin/server'; import { migrateLegacyActions } from '../lib'; @@ -84,6 +90,7 @@ const rulesClientParams: jest.Mocked = { isAuthenticationTypeAPIKey: jest.fn(), getAuthenticationAPIKey: jest.fn(), connectorAdapterRegistry: new ConnectorAdapterRegistry(), + isSystemAction: jest.fn(), getAlertIndicesAlias: jest.fn(), alertsService: null, }; @@ -109,6 +116,7 @@ setGlobalDate(); describe('bulkEnableRules', () => { let rulesClient: RulesClient; + let actionsClient: jest.Mocked; const mockCreatePointInTimeFinderAsInternalUser = ( response = { saved_objects: [disabledRule1, disabledRule2] } @@ -150,11 +158,14 @@ describe('bulkEnableRules', () => { }); mockCreatePointInTimeFinderAsInternalUser(); mockUnsecuredSavedObjectFind(2); + actionsClient = (await rulesClientParams.getActionsClient()) as jest.Mocked; + actionsClient.isSystemAction.mockImplementation((id: string) => id === 'system_action:id'); + rulesClientParams.getActionsClient.mockResolvedValue(actionsClient); }); test('should enable two rule', async () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, enabledRule2], + saved_objects: [enabledRuleForBulkOps1, enabledRuleForBulkOps2], }); const result = await rulesClient.bulkEnableRules({ filter: 'fake_filter' }); @@ -180,15 +191,48 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1, returnedRule2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], total: 2, taskIdsFailedToBeEnabled: [], }); }); + test('should enable two rule and return right actions', async () => { + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ + saved_objects: [enabledRuleForBulkOpsWithActions1, enabledRuleForBulkOpsWithActions2], + }); + + const result = await rulesClient.bulkDisableRules({ filter: 'fake_filter' }); + + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledTimes(1); + expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledWith( + expect.arrayContaining([ + expect.objectContaining({ + id: 'id1', + attributes: expect.objectContaining({ + enabled: false, + }), + }), + expect.objectContaining({ + id: 'id2', + attributes: expect.objectContaining({ + enabled: false, + }), + }), + ]), + { overwrite: true } + ); + + expect(result).toStrictEqual({ + errors: [], + rules: [returnedRuleForBulkEnableWithActions1, returnedRuleForBulkEnableWithActions2], + total: 2, + }); + }); + test('should try to enable rules, one successful and one with 500 error', async () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, savedObjectWith500Error], + saved_objects: [enabledRuleForBulkOps1, savedObjectWith500Error], }); const result = await rulesClient.bulkEnableRules({ filter: 'fake_filter' }); @@ -208,7 +252,7 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [{ message: 'UPS', rule: { id: 'id2', name: 'fakeName' }, status: 500 }], - rules: [returnedRule1], + rules: [returnedRuleForBulkOps1], total: 2, taskIdsFailedToBeEnabled: [], }); @@ -217,7 +261,7 @@ describe('bulkEnableRules', () => { test('should try to enable rules, one successful and one with 409 error, which will not be deleted with retry', async () => { unsecuredSavedObjectsClient.bulkCreate .mockResolvedValueOnce({ - saved_objects: [enabledRule1, savedObjectWith409Error], + saved_objects: [enabledRuleForBulkOps1, savedObjectWith409Error], }) .mockResolvedValueOnce({ saved_objects: [savedObjectWith409Error], @@ -261,7 +305,7 @@ describe('bulkEnableRules', () => { expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledTimes(4); expect(result).toStrictEqual({ errors: [{ message: 'UPS', rule: { id: 'id2', name: 'fakeName' }, status: 409 }], - rules: [returnedRule1], + rules: [returnedRuleForBulkOps1], total: 2, taskIdsFailedToBeEnabled: [], }); @@ -270,10 +314,10 @@ describe('bulkEnableRules', () => { test('should try to enable rules, one successful and one with 409 error, which successfully will be deleted with retry', async () => { unsecuredSavedObjectsClient.bulkCreate .mockResolvedValueOnce({ - saved_objects: [enabledRule1, savedObjectWith409Error], + saved_objects: [enabledRuleForBulkOps1, savedObjectWith409Error], }) .mockResolvedValueOnce({ - saved_objects: [enabledRule2], + saved_objects: [enabledRuleForBulkOps2], }); encryptedSavedObjects.createPointInTimeFinderDecryptedAsInternalUser = jest @@ -302,7 +346,7 @@ describe('bulkEnableRules', () => { expect(unsecuredSavedObjectsClient.bulkCreate).toHaveBeenCalledTimes(2); expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1, returnedRule2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], total: 2, taskIdsFailedToBeEnabled: [], }); @@ -377,10 +421,10 @@ describe('bulkEnableRules', () => { test('should skip rule if it is already enabled', async () => { mockCreatePointInTimeFinderAsInternalUser({ - saved_objects: [disabledRule1, enabledRule2], + saved_objects: [disabledRule1, enabledRuleForBulkOps2], }); unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1], + saved_objects: [enabledRuleForBulkOps1], }); const result = await rulesClient.bulkEnableRules({ filter: 'fake_filter' }); @@ -400,7 +444,7 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1], + rules: [returnedRuleForBulkOps1], total: 2, taskIdsFailedToBeEnabled: [], }); @@ -409,7 +453,7 @@ describe('bulkEnableRules', () => { describe('taskManager', () => { test('should return task id if enabling task failed', async () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, enabledRule2], + saved_objects: [enabledRuleForBulkOps1, enabledRuleForBulkOps2], }); taskManager.bulkEnable.mockImplementation(async () => ({ tasks: [taskManagerMock.createTask({ id: 'id1' })], @@ -437,7 +481,7 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1, returnedRule2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], total: 2, taskIdsFailedToBeEnabled: ['id2'], }); @@ -445,7 +489,7 @@ describe('bulkEnableRules', () => { test('should not throw an error if taskManager throw an error', async () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, enabledRule2], + saved_objects: [enabledRuleForBulkOps1, enabledRuleForBulkOps2], }); taskManager.bulkEnable.mockImplementation(() => { throw new Error('UPS'); @@ -460,7 +504,7 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1, returnedRule2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], taskIdsFailedToBeEnabled: ['id1', 'id2'], total: 2, }); @@ -468,7 +512,7 @@ describe('bulkEnableRules', () => { test('should call task manager bulkEnable for two tasks', async () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, enabledRule2], + saved_objects: [enabledRuleForBulkOps1, enabledRuleForBulkOps2], }); await rulesClient.bulkEnableRules({ filter: 'fake_filter' }); @@ -479,7 +523,7 @@ describe('bulkEnableRules', () => { test('should should call task manager bulkEnable only for one task, if one rule have an error', async () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, savedObjectWith500Error], + saved_objects: [enabledRuleForBulkOps1, savedObjectWith500Error], }); await rulesClient.bulkEnableRules({ filter: 'fake_filter' }); @@ -490,10 +534,10 @@ describe('bulkEnableRules', () => { test('should skip task if rule is already enabled', async () => { mockCreatePointInTimeFinderAsInternalUser({ - saved_objects: [disabledRule1, enabledRule2], + saved_objects: [disabledRule1, enabledRuleForBulkOps2], }); unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1], + saved_objects: [enabledRuleForBulkOps1], }); taskManager.bulkEnable.mockImplementation( @@ -533,7 +577,7 @@ describe('bulkEnableRules', () => { ownerId: null, }); unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, enabledRule2], + saved_objects: [enabledRuleForBulkOps1, enabledRuleForBulkOps2], }); const result = await rulesClient.bulkEnableRules({ ids: ['id1', 'id2'] }); @@ -580,7 +624,7 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1, returnedRule2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], total: 2, taskIdsFailedToBeEnabled: [], }); @@ -617,7 +661,7 @@ describe('bulkEnableRules', () => { ownerId: null, }); unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, enabledRule2], + saved_objects: [enabledRuleForBulkOps1, enabledRuleForBulkOps2], }); const result = await rulesClient.bulkEnableRules({ ids: ['id1', 'id2'] }); @@ -663,7 +707,7 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1, returnedRule2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], total: 2, taskIdsFailedToBeEnabled: [], }); @@ -700,7 +744,7 @@ describe('bulkEnableRules', () => { ownerId: null, }); unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1, enabledRule2], + saved_objects: [enabledRuleForBulkOps1, enabledRuleForBulkOps2], }); const result = await rulesClient.bulkEnableRules({ ids: ['id1', 'id2'] }); @@ -749,7 +793,7 @@ describe('bulkEnableRules', () => { expect(result).toStrictEqual({ errors: [], - rules: [returnedRule1, returnedRule2], + rules: [returnedRuleForBulkOps1, returnedRuleForBulkOps2], total: 2, taskIdsFailedToBeEnabled: [], }); @@ -761,7 +805,7 @@ describe('bulkEnableRules', () => { test('logs audit event when enabling rules', async () => { unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [enabledRule1], + saved_objects: [enabledRuleForBulkOps1], }); await rulesClient.bulkEnableRules({ filter: 'fake_filter' }); @@ -812,32 +856,38 @@ describe('bulkEnableRules', () => { .mockResolvedValueOnce({ close: jest.fn(), find: function* asyncGenerator() { - yield { saved_objects: [disabledRule1, siemRule1, siemRule2] }; + yield { + saved_objects: [ + disabledRuleForBulkDisable1, + siemRuleForBulkOps1, + siemRuleForBulkOps2, + ], + }; }, }); unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ - saved_objects: [disabledRule1, siemRule1, siemRule2], + saved_objects: [disabledRuleForBulkDisable1, siemRuleForBulkOps1, siemRuleForBulkOps2], }); await rulesClient.bulkEnableRules({ filter: 'fake_filter' }); expect(migrateLegacyActions).toHaveBeenCalledTimes(3); expect(migrateLegacyActions).toHaveBeenCalledWith(expect.any(Object), { - attributes: disabledRule1.attributes, - ruleId: disabledRule1.id, + attributes: disabledRuleForBulkDisable1.attributes, + ruleId: disabledRuleForBulkDisable1.id, actions: [], references: [], }); expect(migrateLegacyActions).toHaveBeenCalledWith(expect.any(Object), { attributes: expect.objectContaining({ consumer: AlertConsumers.SIEM }), - ruleId: siemRule1.id, + ruleId: siemRuleForBulkOps1.id, actions: [], references: [], }); expect(migrateLegacyActions).toHaveBeenCalledWith(expect.any(Object), { attributes: expect.objectContaining({ consumer: AlertConsumers.SIEM }), - ruleId: siemRule2.id, + ruleId: siemRuleForBulkOps2.id, actions: [], references: [], }); diff --git a/x-pack/plugins/alerting/server/rules_client/tests/test_helpers.ts b/x-pack/plugins/alerting/server/rules_client/tests/test_helpers.ts index ac67d90ec9d51..405c6a505a7ee 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/test_helpers.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/test_helpers.ts @@ -147,6 +147,64 @@ export const enabledRuleForBulkOps2 = { }, }; +export const enabledRuleForBulkOpsWithActions1 = { + ...defaultRuleForBulkDelete, + attributes: { + ...defaultRuleForBulkDelete.attributes, + enabled: true, + scheduledTaskId: 'id1', + apiKey: Buffer.from('123:abc').toString('base64'), + actions: [ + { + uuid: '1', + id: 'system_action:id', + actionTypeId: '1', + actionRef: '1', + params: { + foo: true, + }, + }, + ], + }, + references: [ + { + id: 'system_action:id', + name: '1', + type: 'action', + }, + ], +}; + +export const enabledRuleForBulkOpsWithActions2 = { + ...defaultRuleForBulkDelete, + id: 'id2', + attributes: { + ...defaultRuleForBulkDelete.attributes, + enabled: true, + scheduledTaskId: 'id2', + apiKey: Buffer.from('321:abc').toString('base64'), + actions: [ + { + uuid: '2', + id: 'default_action:id', + group: 'default', + actionTypeId: '2', + actionRef: '2', + params: { + foo: true, + }, + }, + ], + }, + references: [ + { + id: 'default_action:id', + name: '2', + type: 'action', + }, + ], +}; + export const disabledRuleForBulkOpsWithActions1 = { ...defaultRuleForBulkDelete, attributes: { @@ -361,7 +419,7 @@ export const returnedRule2 = { snoozeSchedule: [], }; -export const returnedRuleForBulkDelete1 = { +export const returnedRuleForBulkOps1 = { actions: [], alertTypeId: 'fakeType', consumer: 'fakeConsumer', @@ -386,7 +444,7 @@ export const returnedRuleForBulkDelete1 = { revision: 1, }; -export const returnedRuleForBulkDelete2 = { +export const returnedRuleForBulkOps2 = { actions: [], alertTypeId: 'fakeType', consumer: 'fakeConsumer', @@ -411,7 +469,7 @@ export const returnedRuleForBulkDelete2 = { revision: 1, }; -export const returnedRuleForBulkDelete3 = { +export const returnedRuleForBulkOps3 = { actions: [], alertTypeId: 'fakeType', apiKeyCreatedByUser: true, @@ -438,12 +496,12 @@ export const returnedRuleForBulkDelete3 = { }; export const returnedRuleForBulkDisable1 = { - ...returnedRuleForBulkDelete1, + ...returnedRuleForBulkOps1, enabled: false, }; export const returnedRuleForBulkDisable2 = { - ...returnedRuleForBulkDelete2, + ...returnedRuleForBulkOps2, enabled: false, }; @@ -478,6 +536,37 @@ export const returnedRuleForBulkDisableWithActions2 = { ], }; +export const returnedRuleForBulkEnableWithActions1 = { + ...returnedRuleForBulkOps1, + actions: [ + { + actionTypeId: '1', + id: 'system_action:id', + params: { + foo: true, + }, + type: 'system', + uuid: '1', + }, + ], +}; + +export const returnedRuleForBulkEnableWithActions2 = { + ...returnedRuleForBulkOps2, + actions: [ + { + actionTypeId: '2', + group: 'default', + id: 'default_action:id', + params: { + foo: true, + }, + type: 'default', + uuid: '2', + }, + ], +}; + export const returnedDisabledRule1 = { ...returnedRule1, enabled: false,