mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[ResponseOps][Rules] Version disable rule route (#188659)
## Summary Parent Issue: #187572 Versions the `POST /rule/{id}/_disable` endpoint. ### 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
This commit is contained in:
parent
2c08b0f290
commit
425d6b10a7
22 changed files with 213 additions and 102 deletions
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { disableRuleRequestBodySchema, disableRuleRequestParamsSchema } from './schemas/latest';
|
||||
export {
|
||||
disableRuleRequestBodySchema as disableRuleRequestBodySchemaV1,
|
||||
disableRuleRequestParamsSchema as disableRuleRequestParamsSchemaV1,
|
||||
} from './schemas/v1';
|
||||
|
||||
export type { DisableRuleRequestBody, DisableRuleRequestParams } from './types/latest';
|
||||
export type {
|
||||
DisableRuleRequestBody as DisableRuleRequestBodyV1,
|
||||
DisableRuleRequestParams as DisableRuleRequestParamsV1,
|
||||
} from './types/v1';
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
|
||||
export const disableRuleRequestBodySchema = schema.nullable(
|
||||
schema.maybe(
|
||||
schema.object({
|
||||
untrack: schema.maybe(schema.boolean({ defaultValue: false })),
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
export const disableRuleRequestParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './v1';
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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 type { TypeOf } from '@kbn/config-schema';
|
||||
import { disableRuleRequestBodySchemaV1, disableRuleRequestParamsSchemaV1 } from '..';
|
||||
|
||||
export type DisableRuleRequestBody = TypeOf<typeof disableRuleRequestBodySchemaV1>;
|
||||
export type DisableRuleRequestParams = TypeOf<typeof disableRuleRequestParamsSchemaV1>;
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||
|
||||
import { RulesClient, ConstructorOptions } from '../rules_client';
|
||||
import { RulesClient, ConstructorOptions } from '../../../../rules_client/rules_client';
|
||||
import {
|
||||
savedObjectsClientMock,
|
||||
loggingSystemMock,
|
||||
|
@ -14,29 +14,29 @@ import {
|
|||
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 { 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 { AlertingAuthorization } from '../../../../authorization/alerting_authorization';
|
||||
import { ActionsAuthorization } from '@kbn/actions-plugin/server';
|
||||
import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks';
|
||||
import { getBeforeSetup, setGlobalDate } from './lib';
|
||||
import { getBeforeSetup, setGlobalDate } from '../../../../rules_client/tests/lib';
|
||||
import { eventLoggerMock } from '@kbn/event-log-plugin/server/event_logger.mock';
|
||||
import { TaskStatus } from '@kbn/task-manager-plugin/server';
|
||||
import { migrateLegacyActions } from '../lib';
|
||||
import { migrateLegacyActionsMock } from '../lib/siem_legacy_actions/retrieve_migrated_legacy_actions.mock';
|
||||
import { ConnectorAdapterRegistry } from '../../connector_adapters/connector_adapter_registry';
|
||||
import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects';
|
||||
import { backfillClientMock } from '../../backfill_client/backfill_client.mock';
|
||||
import { migrateLegacyActions } from '../../../../rules_client/lib';
|
||||
import { migrateLegacyActionsMock } from '../../../../rules_client/lib/siem_legacy_actions/retrieve_migrated_legacy_actions.mock';
|
||||
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('../lib/siem_legacy_actions/migrate_legacy_actions', () => {
|
||||
jest.mock('../../../../rules_client/lib/siem_legacy_actions/migrate_legacy_actions', () => {
|
||||
return {
|
||||
migrateLegacyActions: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation', () => ({
|
||||
jest.mock('../../../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation', () => ({
|
||||
bulkMarkApiKeysForInvalidation: jest.fn(),
|
||||
}));
|
||||
|
||||
|
@ -107,7 +107,7 @@ beforeEach(() => {
|
|||
|
||||
setGlobalDate();
|
||||
|
||||
describe('disable()', () => {
|
||||
describe('disableRule()', () => {
|
||||
let rulesClient: RulesClient;
|
||||
const existingRule = {
|
||||
id: '1',
|
||||
|
@ -158,7 +158,7 @@ describe('disable()', () => {
|
|||
|
||||
describe('authorization', () => {
|
||||
test('ensures user is authorised to disable this type of rule under the consumer', async () => {
|
||||
await rulesClient.disable({ id: '1' });
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
|
||||
expect(authorization.ensureAuthorized).toHaveBeenCalledWith({
|
||||
entity: 'rule',
|
||||
|
@ -173,7 +173,7 @@ describe('disable()', () => {
|
|||
new Error(`Unauthorized to disable a "myType" alert for "myApp"`)
|
||||
);
|
||||
|
||||
await expect(rulesClient.disable({ id: '1' })).rejects.toMatchInlineSnapshot(
|
||||
await expect(rulesClient.disableRule({ id: '1' })).rejects.toMatchInlineSnapshot(
|
||||
`[Error: Unauthorized to disable a "myType" alert for "myApp"]`
|
||||
);
|
||||
|
||||
|
@ -188,7 +188,7 @@ describe('disable()', () => {
|
|||
|
||||
describe('auditLogger', () => {
|
||||
test('logs audit event when disabling a rule', async () => {
|
||||
await rulesClient.disable({ id: '1' });
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
expect(auditLogger.log).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
event: expect.objectContaining({
|
||||
|
@ -203,7 +203,7 @@ describe('disable()', () => {
|
|||
test('logs audit event when not authorised to disable a rule', async () => {
|
||||
authorization.ensureAuthorized.mockRejectedValue(new Error('Unauthorized'));
|
||||
|
||||
await expect(rulesClient.disable({ id: '1' })).rejects.toThrow();
|
||||
await expect(rulesClient.disableRule({ id: '1' })).rejects.toThrow();
|
||||
expect(auditLogger.log).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
event: expect.objectContaining({
|
||||
|
@ -225,8 +225,8 @@ describe('disable()', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('disables an rule', async () => {
|
||||
await rulesClient.disable({ id: '1' });
|
||||
test('disables a rule', async () => {
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled();
|
||||
expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
|
@ -304,7 +304,7 @@ describe('disable()', () => {
|
|||
},
|
||||
ownerId: null,
|
||||
});
|
||||
await rulesClient.disable({ id: '1', untrack: true });
|
||||
await rulesClient.disableRule({ id: '1', untrack: true });
|
||||
expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled();
|
||||
expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
|
@ -393,7 +393,7 @@ describe('disable()', () => {
|
|||
|
||||
test('disables the rule even if unable to retrieve task manager doc to generate untrack event log events', async () => {
|
||||
taskManager.get.mockRejectedValueOnce(new Error('Fail'));
|
||||
await rulesClient.disable({ id: '1', untrack: true });
|
||||
await rulesClient.disableRule({ id: '1', untrack: true });
|
||||
expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled();
|
||||
expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
|
@ -441,12 +441,12 @@ describe('disable()', () => {
|
|||
|
||||
expect(eventLogger.logEvent).toHaveBeenCalledTimes(0);
|
||||
expect(rulesClientParams.logger.warn).toHaveBeenCalledWith(
|
||||
`rulesClient.disable('1') - Could not write untrack events - Fail`
|
||||
`rulesClient.disableRule('1') - Could not write untrack events - Fail`
|
||||
);
|
||||
});
|
||||
|
||||
test('should not untrack rule alert if untrack is false', async () => {
|
||||
await rulesClient.disable({ id: '1', untrack: false });
|
||||
await rulesClient.disableRule({ id: '1', untrack: false });
|
||||
expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled();
|
||||
expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
|
@ -496,7 +496,7 @@ describe('disable()', () => {
|
|||
|
||||
test('falls back when getDecryptedAsInternalUser throws an error', async () => {
|
||||
encryptedSavedObjects.getDecryptedAsInternalUser.mockRejectedValueOnce(new Error('Fail'));
|
||||
await rulesClient.disable({ id: '1' });
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
expect(unsecuredSavedObjectsClient.get).toHaveBeenCalledWith(RULE_SAVED_OBJECT_TYPE, '1');
|
||||
expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
|
@ -548,7 +548,7 @@ describe('disable()', () => {
|
|||
},
|
||||
});
|
||||
|
||||
await rulesClient.disable({ id: '1' });
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
expect(unsecuredSavedObjectsClient.update).not.toHaveBeenCalled();
|
||||
expect(taskManager.bulkDisable).not.toHaveBeenCalled();
|
||||
expect(taskManager.removeIfExists).not.toHaveBeenCalledWith();
|
||||
|
@ -557,7 +557,7 @@ describe('disable()', () => {
|
|||
test('swallows error when failing to load decrypted saved object', async () => {
|
||||
encryptedSavedObjects.getDecryptedAsInternalUser.mockRejectedValueOnce(new Error('Fail'));
|
||||
|
||||
await rulesClient.disable({ id: '1' });
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
expect(unsecuredSavedObjectsClient.update).toHaveBeenCalled();
|
||||
expect(taskManager.bulkDisable).toHaveBeenCalled();
|
||||
expect(taskManager.removeIfExists).not.toHaveBeenCalledWith();
|
||||
|
@ -569,7 +569,7 @@ describe('disable()', () => {
|
|||
test('throws when unsecuredSavedObjectsClient update fails', async () => {
|
||||
unsecuredSavedObjectsClient.update.mockRejectedValueOnce(new Error('Failed to update'));
|
||||
|
||||
await expect(rulesClient.disable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(rulesClient.disableRule({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Failed to update"`
|
||||
);
|
||||
expect(taskManager.bulkDisable).not.toHaveBeenCalled();
|
||||
|
@ -579,12 +579,32 @@ describe('disable()', () => {
|
|||
test('throws when failing to disable task', async () => {
|
||||
taskManager.bulkDisable.mockRejectedValueOnce(new Error('Failed to disable task'));
|
||||
|
||||
await expect(rulesClient.disable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(rulesClient.disableRule({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Failed to disable task"`
|
||||
);
|
||||
expect(taskManager.removeIfExists).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
test('throws if id param does not match the schema', async () => {
|
||||
await expect(
|
||||
// @ts-ignore: this is what we are testing
|
||||
rulesClient.disableRule({ id: 1 })
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Error validating disable rule parameters - [id]: expected value of type [string] but got [number]"`
|
||||
);
|
||||
expect(taskManager.removeIfExists).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
test('throws if untrack param does not match the schema', async () => {
|
||||
await expect(
|
||||
// @ts-ignore: this is what we are testing
|
||||
rulesClient.disableRule({ id: '1', untrack: 'foo' })
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Error validating disable rule parameters - [untrack]: expected value of type [boolean] but got [string]"`
|
||||
);
|
||||
expect(taskManager.removeIfExists).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
test('removes task document if scheduled task id does not match rule id', async () => {
|
||||
encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValue({
|
||||
...existingRule,
|
||||
|
@ -593,7 +613,7 @@ describe('disable()', () => {
|
|||
scheduledTaskId: 'task-123',
|
||||
},
|
||||
});
|
||||
await rulesClient.disable({ id: '1' });
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled();
|
||||
expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
|
@ -644,7 +664,7 @@ describe('disable()', () => {
|
|||
},
|
||||
});
|
||||
taskManager.removeIfExists.mockRejectedValueOnce(new Error('Failed to remove task'));
|
||||
await expect(rulesClient.disable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
await expect(rulesClient.disableRule({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Failed to remove task"`
|
||||
);
|
||||
expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled();
|
||||
|
@ -697,7 +717,7 @@ describe('disable()', () => {
|
|||
encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValue(existingDecryptedSiemRule);
|
||||
(migrateLegacyActions as jest.Mock).mockResolvedValue(migrateLegacyActionsMock);
|
||||
|
||||
await rulesClient.disable({ id: '1' });
|
||||
await rulesClient.disableRule({ id: '1' });
|
||||
|
||||
expect(migrateLegacyActions).toHaveBeenCalledWith(expect.any(Object), {
|
||||
attributes: expect.objectContaining({ consumer: AlertConsumers.SIEM }),
|
|
@ -6,46 +6,43 @@
|
|||
*/
|
||||
import type { SavedObjectReference } from '@kbn/core/server';
|
||||
|
||||
import { RawRule } from '../../types';
|
||||
import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization';
|
||||
import { retryIfConflicts } from '../../lib/retry_if_conflicts';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
||||
import { RulesClientContext } from '../types';
|
||||
import { untrackRuleAlerts, updateMeta, migrateLegacyActions } from '../lib';
|
||||
import { RuleAttributes } from '../../data/rule/types';
|
||||
import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects';
|
||||
import Boom from '@hapi/boom';
|
||||
import { RawRule } from '../../../../types';
|
||||
import { WriteOperations, AlertingAuthorizationEntity } from '../../../../authorization';
|
||||
import { retryIfConflicts } from '../../../../lib/retry_if_conflicts';
|
||||
import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events';
|
||||
import { RulesClientContext } from '../../../../rules_client/types';
|
||||
import { untrackRuleAlerts, updateMeta, migrateLegacyActions } from '../../../../rules_client/lib';
|
||||
import { RuleAttributes } from '../../../../data/rule/types';
|
||||
import { RULE_SAVED_OBJECT_TYPE } from '../../../../saved_objects';
|
||||
import { DisableRuleParams } from './types';
|
||||
import { disableRuleParamsSchema } from './schemas';
|
||||
|
||||
export async function disable(
|
||||
export async function disableRule(
|
||||
context: RulesClientContext,
|
||||
{
|
||||
id,
|
||||
untrack = false,
|
||||
}: {
|
||||
id: string;
|
||||
untrack?: boolean;
|
||||
}
|
||||
{ id, untrack = false }: DisableRuleParams
|
||||
): Promise<void> {
|
||||
return await retryIfConflicts(
|
||||
context.logger,
|
||||
`rulesClient.disable('${id}')`,
|
||||
`rulesClient.disableRule('${id}')`,
|
||||
async () => await disableWithOCC(context, { id, untrack })
|
||||
);
|
||||
}
|
||||
|
||||
async function disableWithOCC(
|
||||
context: RulesClientContext,
|
||||
{
|
||||
id,
|
||||
untrack = false,
|
||||
}: {
|
||||
id: string;
|
||||
untrack?: boolean;
|
||||
}
|
||||
{ id, untrack = false }: DisableRuleParams
|
||||
) {
|
||||
let attributes: RawRule;
|
||||
let version: string | undefined;
|
||||
let references: SavedObjectReference[];
|
||||
|
||||
try {
|
||||
disableRuleParamsSchema.validate({ id, untrack });
|
||||
} catch (error) {
|
||||
throw Boom.badRequest(`Error validating disable rule parameters - ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const decryptedAlert =
|
||||
await context.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawRule>(
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { disableRule } from './disable_rule';
|
||||
export type { DisableRuleParams } from './types';
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
|
||||
export const disableRuleParamsSchema = schema.object({
|
||||
id: schema.string(),
|
||||
untrack: schema.maybe(schema.boolean({ defaultValue: false })),
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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 type { TypeOf } from '@kbn/config-schema';
|
||||
import { disableRuleParamsSchema } from '../schemas';
|
||||
|
||||
export type DisableRuleParams = TypeOf<typeof disableRuleParamsSchema>;
|
|
@ -18,7 +18,7 @@ import { getRuleRoute, getInternalRuleRoute } from './rule/apis/get/get_rule_rou
|
|||
import { updateRuleRoute } from './rule/apis/update/update_rule_route';
|
||||
import { deleteRuleRoute } from './rule/apis/delete/delete_rule_route';
|
||||
import { aggregateRulesRoute } from './rule/apis/aggregate/aggregate_rules_route';
|
||||
import { disableRuleRoute } from './disable_rule';
|
||||
import { disableRuleRoute } from './rule/apis/disable/disable_rule_route';
|
||||
import { enableRuleRoute } from './rule/apis/enable/enable_rule';
|
||||
import { findRulesRoute, findInternalRulesRoute } from './rule/apis/find/find_rules_route';
|
||||
import { getRuleAlertSummaryRoute } from './get_rule_alert_summary';
|
||||
|
|
|
@ -38,7 +38,7 @@ describe('disableAlertRoute', () => {
|
|||
|
||||
expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_disable"`);
|
||||
|
||||
rulesClient.disable.mockResolvedValueOnce();
|
||||
rulesClient.disableRule.mockResolvedValueOnce();
|
||||
|
||||
const [context, req, res] = mockHandlerArguments(
|
||||
{ rulesClient },
|
||||
|
@ -52,8 +52,8 @@ describe('disableAlertRoute', () => {
|
|||
|
||||
expect(await handler(context, req, res)).toEqual(undefined);
|
||||
|
||||
expect(rulesClient.disable).toHaveBeenCalledTimes(1);
|
||||
expect(rulesClient.disable.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(rulesClient.disableRule).toHaveBeenCalledTimes(1);
|
||||
expect(rulesClient.disableRule.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
|
@ -72,7 +72,7 @@ describe('disableAlertRoute', () => {
|
|||
|
||||
const [, handler] = router.post.mock.calls[0];
|
||||
|
||||
rulesClient.disable.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
|
||||
rulesClient.disableRule.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
|
||||
|
||||
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
|
||||
'ok',
|
||||
|
|
|
@ -39,7 +39,7 @@ export const disableAlertRoute = (
|
|||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
const { id } = req.params;
|
||||
try {
|
||||
await rulesClient.disable({ id });
|
||||
await rulesClient.disableRule({ id });
|
||||
return res.noContent();
|
||||
} catch (e) {
|
||||
if (e instanceof RuleTypeDisabledError) {
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { disableRuleRoute } from './disable_rule';
|
||||
import { disableRuleRoute } from './disable_rule_route';
|
||||
import { httpServiceMock } from '@kbn/core/server/mocks';
|
||||
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 { 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';
|
||||
|
||||
const rulesClient = rulesClientMock.create();
|
||||
|
||||
jest.mock('../lib/license_api_access', () => ({
|
||||
jest.mock('../../../../lib/license_api_access', () => ({
|
||||
verifyApiAccess: jest.fn(),
|
||||
}));
|
||||
|
||||
|
@ -33,7 +33,7 @@ describe('disableRuleRoute', () => {
|
|||
|
||||
expect(config.path).toMatchInlineSnapshot(`"/api/alerting/rule/{id}/_disable"`);
|
||||
|
||||
rulesClient.disable.mockResolvedValueOnce();
|
||||
rulesClient.disableRule.mockResolvedValueOnce();
|
||||
|
||||
const [context, req, res] = mockHandlerArguments(
|
||||
{ rulesClient },
|
||||
|
@ -47,8 +47,8 @@ describe('disableRuleRoute', () => {
|
|||
|
||||
expect(await handler(context, req, res)).toEqual(undefined);
|
||||
|
||||
expect(rulesClient.disable).toHaveBeenCalledTimes(1);
|
||||
expect(rulesClient.disable.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
expect(rulesClient.disableRule).toHaveBeenCalledTimes(1);
|
||||
expect(rulesClient.disableRule.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
|
@ -68,7 +68,7 @@ describe('disableRuleRoute', () => {
|
|||
|
||||
const [, handler] = router.post.mock.calls[0];
|
||||
|
||||
rulesClient.disable.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
|
||||
rulesClient.disableRule.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
|
||||
|
||||
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
|
||||
'ok',
|
|
@ -6,22 +6,15 @@
|
|||
*/
|
||||
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ILicenseState, RuleTypeDisabledError } from '../lib';
|
||||
import { verifyAccessAndContext } from './lib';
|
||||
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
|
||||
|
||||
const paramSchema = schema.object({
|
||||
id: schema.string(),
|
||||
});
|
||||
|
||||
const bodySchema = schema.nullable(
|
||||
schema.maybe(
|
||||
schema.object({
|
||||
untrack: schema.maybe(schema.boolean({ defaultValue: false })),
|
||||
})
|
||||
)
|
||||
);
|
||||
import {
|
||||
disableRuleRequestParamsSchemaV1,
|
||||
disableRuleRequestBodySchemaV1,
|
||||
DisableRuleRequestParamsV1,
|
||||
DisableRuleRequestBodyV1,
|
||||
} from '../../../../../common/routes/rule/apis/disable';
|
||||
import { ILicenseState, RuleTypeDisabledError } from '../../../../lib';
|
||||
import { verifyAccessAndContext } from '../../../lib';
|
||||
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../../../../types';
|
||||
|
||||
export const disableRuleRoute = (
|
||||
router: IRouter<AlertingRequestHandlerContext>,
|
||||
|
@ -32,20 +25,24 @@ export const disableRuleRoute = (
|
|||
path: `${BASE_ALERTING_API_PATH}/rule/{id}/_disable`,
|
||||
options: {
|
||||
access: 'public',
|
||||
summary: `Disable a rule`,
|
||||
summary: 'Disable a rule',
|
||||
},
|
||||
validate: {
|
||||
params: paramSchema,
|
||||
body: bodySchema,
|
||||
params: disableRuleRequestParamsSchemaV1,
|
||||
body: disableRuleRequestBodySchemaV1,
|
||||
},
|
||||
},
|
||||
router.handleLegacyErrors(
|
||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||
const rulesClient = (await context.alerting).getRulesClient();
|
||||
const { id } = req.params;
|
||||
const { untrack = false } = req.body || {};
|
||||
const { id }: DisableRuleRequestParamsV1 = req.params;
|
||||
const body: DisableRuleRequestBodyV1 = req.body || {};
|
||||
const { untrack = false } = body;
|
||||
|
||||
const disableParams = { id, untrack };
|
||||
|
||||
try {
|
||||
await rulesClient.disable({ id, untrack });
|
||||
await rulesClient.disableRule(disableParams);
|
||||
return res.noContent();
|
||||
} catch (e) {
|
||||
if (e instanceof RuleTypeDisabledError) {
|
|
@ -21,8 +21,8 @@ const createRulesClientMock = () => {
|
|||
find: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
update: jest.fn(),
|
||||
disableRule: jest.fn(),
|
||||
enableRule: jest.fn(),
|
||||
disable: jest.fn(),
|
||||
updateRuleApiKey: jest.fn(),
|
||||
muteAll: jest.fn(),
|
||||
unmuteAll: jest.fn(),
|
||||
|
|
|
@ -89,7 +89,7 @@ export const untrackRuleAlerts = async (
|
|||
} catch (error) {
|
||||
// this should not block the rest of the disable process
|
||||
context.logger.warn(
|
||||
`rulesClient.disable('${id}') - Could not write untrack events - ${error.message}`
|
||||
`rulesClient.disableRule('${id}') - Could not write untrack events - ${error.message}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -55,7 +55,7 @@ import {
|
|||
import { bulkEnableRules, BulkEnableRulesParams } from '../application/rule/methods/bulk_enable';
|
||||
import { enableRule } from '../application/rule/methods/enable_rule/enable_rule';
|
||||
import { updateRuleApiKey } from '../application/rule/methods/update_api_key/update_rule_api_key';
|
||||
import { disable } from './methods/disable';
|
||||
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';
|
||||
|
@ -75,6 +75,7 @@ import { getBackfill } from '../application/backfill/methods/get';
|
|||
import { findBackfill } from '../application/backfill/methods/find';
|
||||
import { deleteBackfill } from '../application/backfill/methods/delete';
|
||||
import { FindBackfillParams } from '../application/backfill/methods/find/types';
|
||||
import { DisableRuleParams } from '../application/rule/methods/disable';
|
||||
import { EnableRuleParams } from '../application/rule/methods/enable_rule';
|
||||
|
||||
export type ConstructorOptions = Omit<
|
||||
|
@ -166,9 +167,8 @@ export class RulesClient {
|
|||
bulkDisableRules(this.context, options);
|
||||
|
||||
public updateRuleApiKey = (params: { id: string }) => updateRuleApiKey(this.context, params);
|
||||
|
||||
public disableRule = (params: DisableRuleParams) => disableRule(this.context, params);
|
||||
public enableRule = (params: EnableRuleParams) => enableRule(this.context, params);
|
||||
public disable = (options: { id: string; untrack?: boolean }) => disable(this.context, options);
|
||||
|
||||
public snooze = (options: SnoozeRuleOptions) => snoozeRule(this.context, options);
|
||||
public unsnooze = (options: UnsnoozeParams) => unsnoozeRule(this.context, options);
|
||||
|
|
|
@ -173,7 +173,7 @@ async function enable(success: boolean) {
|
|||
|
||||
async function disable(success: boolean) {
|
||||
try {
|
||||
await rulesClient.disable({ id: MockRuleId });
|
||||
await rulesClient.disableRule({ id: MockRuleId });
|
||||
} catch (err) {
|
||||
return expectConflict(success, err);
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ describe('DetectionRulesClient.patchRule', () => {
|
|||
const rule = await detectionRulesClient.patchRule({ rulePatch });
|
||||
|
||||
expect(rule.enabled).toBe(false);
|
||||
expect(rulesClient.disable).toHaveBeenCalledWith(
|
||||
expect(rulesClient.disableRule).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: existingRule.id,
|
||||
})
|
||||
|
|
|
@ -111,7 +111,7 @@ describe('DetectionRulesClient.updateRule', () => {
|
|||
|
||||
await detectionRulesClient.updateRule({ ruleUpdate });
|
||||
|
||||
expect(rulesClient.disable).toHaveBeenCalledWith(
|
||||
expect(rulesClient.disableRule).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: existingRule.id,
|
||||
})
|
||||
|
|
|
@ -22,7 +22,7 @@ export const toggleRuleEnabledOnUpdate = async (
|
|||
updatedRule: RuleResponse
|
||||
): Promise<{ enabled: boolean }> => {
|
||||
if (existingRule.enabled && !updatedRule.enabled) {
|
||||
await rulesClient.disable({ id: existingRule.id });
|
||||
await rulesClient.disableRule({ id: existingRule.id });
|
||||
return { enabled: false };
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue