mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 03:01:21 -04:00
[RAM] HTTP Versioning Rule Mute Alert (#165573)
## Summary Meta Issue: https://github.com/elastic/kibana/issues/157883 Add HTTP versioning to mute alert endpoint
This commit is contained in:
parent
c18513e23d
commit
750c4bedbf
18 changed files with 170 additions and 49 deletions
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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 { muteAlertParamsSchema } from './schemas/latest';
|
||||||
|
export { muteAlertParamsSchema as muteAlertParamsSchemaV1 } from './schemas/v1';
|
||||||
|
|
||||||
|
export type { MuteAlertRequestParams } from './types/latest';
|
||||||
|
export type { MuteAlertRequestParams as MuteAlertRequestParamsV1 } from './types/v1';
|
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* 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 { muteAlertParamsSchema } from './v1';
|
|
@ -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 muteAlertParamsSchema = schema.object({
|
||||||
|
rule_id: schema.string(),
|
||||||
|
alert_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 type { MuteAlertRequestParams } from './v1';
|
|
@ -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 { muteAlertParamsSchemaV1 } from '..';
|
||||||
|
|
||||||
|
export type MuteAlertRequestParams = TypeOf<typeof muteAlertParamsSchemaV1>;
|
|
@ -5,28 +5,37 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Rule } from '../../types';
|
import Boom from '@hapi/boom';
|
||||||
import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization';
|
import { updateRuleSo } from '../../../../data/rule/methods/update_rule_so';
|
||||||
import { retryIfConflicts } from '../../lib/retry_if_conflicts';
|
import { muteAlertParamsSchema } from './schemas';
|
||||||
import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events';
|
import type { MuteAlertParams } from './types';
|
||||||
import { MuteOptions } from '../types';
|
import { Rule } from '../../../../types';
|
||||||
import { RulesClientContext } from '../types';
|
import { WriteOperations, AlertingAuthorizationEntity } from '../../../../authorization';
|
||||||
import { updateMeta } from '../lib';
|
import { retryIfConflicts } from '../../../../lib/retry_if_conflicts';
|
||||||
|
import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events';
|
||||||
|
import { RulesClientContext } from '../../../../rules_client/types';
|
||||||
|
import { updateMeta } from '../../../../rules_client/lib';
|
||||||
|
|
||||||
export async function muteInstance(
|
export async function muteInstance(
|
||||||
context: RulesClientContext,
|
context: RulesClientContext,
|
||||||
{ alertId, alertInstanceId }: MuteOptions
|
params: MuteAlertParams
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
muteAlertParamsSchema.validate(params);
|
||||||
|
} catch (error) {
|
||||||
|
throw Boom.badRequest(`Failed to validate params: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
return await retryIfConflicts(
|
return await retryIfConflicts(
|
||||||
context.logger,
|
context.logger,
|
||||||
`rulesClient.muteInstance('${alertId}')`,
|
`rulesClient.muteInstance('${params.alertId}')`,
|
||||||
async () => await muteInstanceWithOCC(context, { alertId, alertInstanceId })
|
async () => await muteInstanceWithOCC(context, params)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function muteInstanceWithOCC(
|
async function muteInstanceWithOCC(
|
||||||
context: RulesClientContext,
|
context: RulesClientContext,
|
||||||
{ alertId, alertInstanceId }: MuteOptions
|
{ alertId, alertInstanceId }: MuteAlertParams
|
||||||
) {
|
) {
|
||||||
const { attributes, version } = await context.unsecuredSavedObjectsClient.get<Rule>(
|
const { attributes, version } = await context.unsecuredSavedObjectsClient.get<Rule>(
|
||||||
'alert',
|
'alert',
|
||||||
|
@ -68,15 +77,15 @@ async function muteInstanceWithOCC(
|
||||||
const mutedInstanceIds = attributes.mutedInstanceIds || [];
|
const mutedInstanceIds = attributes.mutedInstanceIds || [];
|
||||||
if (!attributes.muteAll && !mutedInstanceIds.includes(alertInstanceId)) {
|
if (!attributes.muteAll && !mutedInstanceIds.includes(alertInstanceId)) {
|
||||||
mutedInstanceIds.push(alertInstanceId);
|
mutedInstanceIds.push(alertInstanceId);
|
||||||
await context.unsecuredSavedObjectsClient.update(
|
await updateRuleSo({
|
||||||
'alert',
|
savedObjectsClient: context.unsecuredSavedObjectsClient,
|
||||||
alertId,
|
savedObjectsUpdateOptions: { version },
|
||||||
updateMeta(context, {
|
id: alertId,
|
||||||
|
updateRuleAttributes: updateMeta(context, {
|
||||||
mutedInstanceIds,
|
mutedInstanceIds,
|
||||||
updatedBy: await context.getUserName(),
|
updatedBy: await context.getUserName(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
}),
|
}),
|
||||||
{ version }
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* 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 { muteAlertParamsSchema } from './mute_alert_params_schema';
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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 muteAlertParamsSchema = schema.object({
|
||||||
|
alertId: schema.string(),
|
||||||
|
alertInstanceId: 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 type { MuteAlertParams } from './mute_alert_params';
|
|
@ -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 { TypeOf } from '@kbn/config-schema';
|
||||||
|
import { muteAlertParamsSchema } from '../schemas';
|
||||||
|
|
||||||
|
export type MuteAlertParams = TypeOf<typeof muteAlertParamsSchema>;
|
|
@ -32,7 +32,7 @@ import { healthRoute } from './health';
|
||||||
import { resolveRuleRoute } from './resolve_rule';
|
import { resolveRuleRoute } from './resolve_rule';
|
||||||
import { ruleTypesRoute } from './rule_types';
|
import { ruleTypesRoute } from './rule_types';
|
||||||
import { muteAllRuleRoute } from './mute_all_rule';
|
import { muteAllRuleRoute } from './mute_all_rule';
|
||||||
import { muteAlertRoute } from './mute_alert';
|
import { muteAlertRoute } from './rule/apis/mute_alert/mute_alert';
|
||||||
import { unmuteAllRuleRoute } from './unmute_all_rule';
|
import { unmuteAllRuleRoute } from './unmute_all_rule';
|
||||||
import { unmuteAlertRoute } from './unmute_alert';
|
import { unmuteAlertRoute } from './unmute_alert';
|
||||||
import { updateRuleApiKeyRoute } from './update_rule_api_key';
|
import { updateRuleApiKeyRoute } from './update_rule_api_key';
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
import { muteAlertRoute } from './mute_alert';
|
import { muteAlertRoute } from './mute_alert';
|
||||||
import { httpServiceMock } from '@kbn/core/server/mocks';
|
import { httpServiceMock } from '@kbn/core/server/mocks';
|
||||||
import { licenseStateMock } from '../lib/license_state.mock';
|
import { licenseStateMock } from '../../../../lib/license_state.mock';
|
||||||
import { mockHandlerArguments } from './_mock_handler_arguments';
|
import { mockHandlerArguments } from '../../../_mock_handler_arguments';
|
||||||
import { rulesClientMock } from '../rules_client.mock';
|
import { rulesClientMock } from '../../../../rules_client.mock';
|
||||||
import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
|
import { RuleTypeDisabledError } from '../../../../lib';
|
||||||
|
|
||||||
const rulesClient = rulesClientMock.create();
|
const rulesClient = rulesClientMock.create();
|
||||||
jest.mock('../lib/license_api_access', () => ({
|
jest.mock('../../../../lib/license_api_access', () => ({
|
||||||
verifyApiAccess: jest.fn(),
|
verifyApiAccess: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -4,26 +4,15 @@
|
||||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { IRouter } from '@kbn/core/server';
|
import { IRouter } from '@kbn/core/server';
|
||||||
import { schema } from '@kbn/config-schema';
|
import { transformRequestParamsToApplicationV1 } from './transforms';
|
||||||
import { ILicenseState, RuleTypeDisabledError } from '../lib';
|
import { ILicenseState, RuleTypeDisabledError } from '../../../../lib';
|
||||||
import { MuteOptions } from '../rules_client';
|
import { verifyAccessAndContext } from '../../../lib';
|
||||||
import { RewriteRequestCase, verifyAccessAndContext } from './lib';
|
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../../../../types';
|
||||||
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
|
import {
|
||||||
|
muteAlertParamsSchemaV1,
|
||||||
const paramSchema = schema.object({
|
MuteAlertRequestParamsV1,
|
||||||
rule_id: schema.string(),
|
} from '../../../../../common/routes/rule/apis/mute_alert';
|
||||||
alert_id: schema.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const rewriteParamsReq: RewriteRequestCase<MuteOptions> = ({
|
|
||||||
rule_id: alertId,
|
|
||||||
alert_id: alertInstanceId,
|
|
||||||
}) => ({
|
|
||||||
alertId,
|
|
||||||
alertInstanceId,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const muteAlertRoute = (
|
export const muteAlertRoute = (
|
||||||
router: IRouter<AlertingRequestHandlerContext>,
|
router: IRouter<AlertingRequestHandlerContext>,
|
||||||
|
@ -33,15 +22,15 @@ export const muteAlertRoute = (
|
||||||
{
|
{
|
||||||
path: `${BASE_ALERTING_API_PATH}/rule/{rule_id}/alert/{alert_id}/_mute`,
|
path: `${BASE_ALERTING_API_PATH}/rule/{rule_id}/alert/{alert_id}/_mute`,
|
||||||
validate: {
|
validate: {
|
||||||
params: paramSchema,
|
params: muteAlertParamsSchemaV1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
router.handleLegacyErrors(
|
router.handleLegacyErrors(
|
||||||
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
verifyAccessAndContext(licenseState, async function (context, req, res) {
|
||||||
const rulesClient = (await context.alerting).getRulesClient();
|
const rulesClient = (await context.alerting).getRulesClient();
|
||||||
const params = rewriteParamsReq(req.params);
|
const params: MuteAlertRequestParamsV1 = req.params;
|
||||||
try {
|
try {
|
||||||
await rulesClient.muteInstance(params);
|
await rulesClient.muteInstance(transformRequestParamsToApplicationV1(params));
|
||||||
return res.noContent();
|
return res.noContent();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof RuleTypeDisabledError) {
|
if (e instanceof RuleTypeDisabledError) {
|
|
@ -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 { transformRequestParamsToApplication } from './transform_request_params_to_application/latest';
|
||||||
|
export { transformRequestParamsToApplication as transformRequestParamsToApplicationV1 } from './transform_request_params_to_application/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 { transformRequestParamsToApplication } from './v1';
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* 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 { MuteAlertParams } from '../../../../../../application/rule/methods/mute_alert/types';
|
||||||
|
import { RewriteRequestCase } from '../../../../../lib';
|
||||||
|
|
||||||
|
export const transformRequestParamsToApplication: RewriteRequestCase<MuteAlertParams> = ({
|
||||||
|
rule_id: alertId,
|
||||||
|
alert_id: alertInstanceId,
|
||||||
|
}) => ({
|
||||||
|
alertId,
|
||||||
|
alertInstanceId,
|
||||||
|
});
|
|
@ -5,9 +5,10 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { MuteAlertParams } from '../application/rule/methods/mute_alert/types';
|
||||||
import { SanitizedRule, RuleTypeParams } from '../types';
|
import { SanitizedRule, RuleTypeParams } from '../types';
|
||||||
import { parseDuration } from '../../common/parse_duration';
|
import { parseDuration } from '../../common/parse_duration';
|
||||||
import { RulesClientContext, BulkOptions, MuteOptions } from './types';
|
import { RulesClientContext, BulkOptions } from './types';
|
||||||
import { clone, CloneArguments } from './methods/clone';
|
import { clone, CloneArguments } from './methods/clone';
|
||||||
import { createRule, CreateRuleParams } from '../application/rule/methods/create';
|
import { createRule, CreateRuleParams } from '../application/rule/methods/create';
|
||||||
import { get, GetParams } from './methods/get';
|
import { get, GetParams } from './methods/get';
|
||||||
|
@ -52,9 +53,9 @@ import { disable } from './methods/disable';
|
||||||
import { snooze, SnoozeParams } from './methods/snooze';
|
import { snooze, SnoozeParams } from './methods/snooze';
|
||||||
import { unsnooze, UnsnoozeParams } from './methods/unsnooze';
|
import { unsnooze, UnsnoozeParams } from './methods/unsnooze';
|
||||||
import { clearExpiredSnoozes } from './methods/clear_expired_snoozes';
|
import { clearExpiredSnoozes } from './methods/clear_expired_snoozes';
|
||||||
|
import { muteInstance } from '../application/rule/methods/mute_alert/mute_instance';
|
||||||
import { muteAll } from './methods/mute_all';
|
import { muteAll } from './methods/mute_all';
|
||||||
import { unmuteAll } from './methods/unmute_all';
|
import { unmuteAll } from './methods/unmute_all';
|
||||||
import { muteInstance } from './methods/mute_instance';
|
|
||||||
import { unmuteInstance } from './methods/unmute_instance';
|
import { unmuteInstance } from './methods/unmute_instance';
|
||||||
import { runSoon } from './methods/run_soon';
|
import { runSoon } from './methods/run_soon';
|
||||||
import { listRuleTypes } from './methods/list_rule_types';
|
import { listRuleTypes } from './methods/list_rule_types';
|
||||||
|
@ -163,8 +164,8 @@ export class RulesClient {
|
||||||
|
|
||||||
public muteAll = (options: { id: string }) => muteAll(this.context, options);
|
public muteAll = (options: { id: string }) => muteAll(this.context, options);
|
||||||
public unmuteAll = (options: { id: string }) => unmuteAll(this.context, options);
|
public unmuteAll = (options: { id: string }) => unmuteAll(this.context, options);
|
||||||
public muteInstance = (options: MuteOptions) => muteInstance(this.context, options);
|
public muteInstance = (options: MuteAlertParams) => muteInstance(this.context, options);
|
||||||
public unmuteInstance = (options: MuteOptions) => unmuteInstance(this.context, options);
|
public unmuteInstance = (options: MuteAlertParams) => unmuteInstance(this.context, options);
|
||||||
|
|
||||||
public runSoon = (options: { id: string }) => runSoon(this.context, options);
|
public runSoon = (options: { id: string }) => runSoon(this.context, options);
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,7 @@ export interface IndexType {
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove once all mute endpoints have been migrated to RuleMuteAlertOptions
|
||||||
export interface MuteOptions extends IndexType {
|
export interface MuteOptions extends IndexType {
|
||||||
alertId: string;
|
alertId: string;
|
||||||
alertInstanceId: string;
|
alertInstanceId: string;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue