mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[alerting] replace internal legacy API calls with new APIs (#121048)
resolves https://github.com/elastic/kibana/issues/116939 Removes the remaining calls to the legacy HTTP alerting endpoints by internal Kibana code.
This commit is contained in:
parent
825e35dcba
commit
b4c44a135e
11 changed files with 698 additions and 115 deletions
25
x-pack/examples/alerting_example/common/types.ts
Normal file
25
x-pack/examples/alerting_example/common/types.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// We don't have types defined for the response objects from our HTTP APIs,
|
||||||
|
// so defining what we need here.
|
||||||
|
|
||||||
|
export interface Rule<T = never> {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
rule_type_id: string;
|
||||||
|
schedule: {
|
||||||
|
interval: string;
|
||||||
|
};
|
||||||
|
params: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RuleTaskState {
|
||||||
|
alerts: Array<{
|
||||||
|
state: Record<string, never>;
|
||||||
|
}>;
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ export function registerNavigation(alerting: AlertingSetup) {
|
||||||
// register default navigation
|
// register default navigation
|
||||||
alerting.registerDefaultNavigation(
|
alerting.registerDefaultNavigation(
|
||||||
ALERTING_EXAMPLE_APP_ID,
|
ALERTING_EXAMPLE_APP_ID,
|
||||||
(alert: SanitizedAlert) => `/alert/${alert.id}`
|
(alert: SanitizedAlert) => `/rule/${alert.id}`
|
||||||
);
|
);
|
||||||
|
|
||||||
registerPeopleInSpaceNavigation(alerting);
|
registerPeopleInSpaceNavigation(alerting);
|
||||||
|
|
|
@ -23,26 +23,27 @@ import { CoreStart } from 'kibana/public';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
|
import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
|
||||||
import {
|
import {
|
||||||
Alert,
|
BASE_ALERTING_API_PATH,
|
||||||
RuleTaskState,
|
INTERNAL_BASE_ALERTING_API_PATH,
|
||||||
LEGACY_BASE_ALERT_API_PATH,
|
|
||||||
} from '../../../../plugins/alerting/common';
|
} from '../../../../plugins/alerting/common';
|
||||||
|
import { Rule, RuleTaskState } from '../../common/types';
|
||||||
|
|
||||||
type Props = RouteComponentProps & {
|
type Props = RouteComponentProps & {
|
||||||
http: CoreStart['http'];
|
http: CoreStart['http'];
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ViewAlertPage = withRouter(({ http, id }: Props) => {
|
export const ViewAlertPage = withRouter(({ http, id }: Props) => {
|
||||||
const [alert, setAlert] = useState<Alert | null>(null);
|
const [alert, setAlert] = useState<Rule | null>(null);
|
||||||
const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
|
const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!alert) {
|
if (!alert) {
|
||||||
http.get<Alert | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`).then(setAlert);
|
http.get<Rule | null>(`${BASE_ALERTING_API_PATH}/rule/${id}`).then(setAlert);
|
||||||
}
|
}
|
||||||
if (!alertState) {
|
if (!alertState) {
|
||||||
http
|
http
|
||||||
.get<RuleTaskState | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`)
|
.get<RuleTaskState | null>(`${INTERNAL_BASE_ALERTING_API_PATH}/rule/${id}/state`)
|
||||||
.then(setAlertState);
|
.then(setAlertState);
|
||||||
}
|
}
|
||||||
}, [alert, alertState, http, id]);
|
}, [alert, alertState, http, id]);
|
||||||
|
@ -60,7 +61,7 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => {
|
||||||
Rule, whose ID is <EuiTextColor color="accent">{`${alert.id}`}</EuiTextColor>.
|
Rule, whose ID is <EuiTextColor color="accent">{`${alert.id}`}</EuiTextColor>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Its RuleType is <EuiTextColor color="accent">{`${alert.alertTypeId}`}</EuiTextColor> and
|
Its RuleType is <EuiTextColor color="accent">{`${alert.rule_type_id}`}</EuiTextColor> and
|
||||||
its scheduled to run at an interval of
|
its scheduled to run at an interval of
|
||||||
<EuiTextColor color="accent"> {`${alert.schedule.interval}`}</EuiTextColor>.
|
<EuiTextColor color="accent"> {`${alert.schedule.interval}`}</EuiTextColor>.
|
||||||
</p>
|
</p>
|
||||||
|
@ -69,7 +70,7 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => {
|
||||||
<EuiText>
|
<EuiText>
|
||||||
<h2>Alerts</h2>
|
<h2>Alerts</h2>
|
||||||
</EuiText>
|
</EuiText>
|
||||||
{isEmpty(alertState.alertInstances) ? (
|
{isEmpty(alertState.alerts) ? (
|
||||||
<EuiCallOut title="No Alerts!" color="warning" iconType="help">
|
<EuiCallOut title="No Alerts!" color="warning" iconType="help">
|
||||||
<p>This Rule doesn't have any active alerts at the moment.</p>
|
<p>This Rule doesn't have any active alerts at the moment.</p>
|
||||||
</EuiCallOut>
|
</EuiCallOut>
|
||||||
|
@ -84,7 +85,7 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => {
|
||||||
</EuiCallOut>
|
</EuiCallOut>
|
||||||
<EuiSpacer size="l" />
|
<EuiSpacer size="l" />
|
||||||
<EuiDescriptionList compressed>
|
<EuiDescriptionList compressed>
|
||||||
{Object.entries(alertState.alertInstances ?? {}).map(([instance, { state }]) => (
|
{Object.entries(alertState.alerts ?? {}).map(([instance, { state }]) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<EuiDescriptionListTitle>{instance}</EuiDescriptionListTitle>
|
<EuiDescriptionListTitle>{instance}</EuiDescriptionListTitle>
|
||||||
<EuiDescriptionListDescription>
|
<EuiDescriptionListDescription>
|
||||||
|
|
|
@ -25,10 +25,10 @@ import { CoreStart } from 'kibana/public';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { ALERTING_EXAMPLE_APP_ID, AlwaysFiringParams } from '../../common/constants';
|
import { ALERTING_EXAMPLE_APP_ID, AlwaysFiringParams } from '../../common/constants';
|
||||||
import {
|
import {
|
||||||
Alert,
|
BASE_ALERTING_API_PATH,
|
||||||
RuleTaskState,
|
INTERNAL_BASE_ALERTING_API_PATH,
|
||||||
LEGACY_BASE_ALERT_API_PATH,
|
|
||||||
} from '../../../../plugins/alerting/common';
|
} from '../../../../plugins/alerting/common';
|
||||||
|
import { Rule, RuleTaskState } from '../../common/types';
|
||||||
|
|
||||||
type Props = RouteComponentProps & {
|
type Props = RouteComponentProps & {
|
||||||
http: CoreStart['http'];
|
http: CoreStart['http'];
|
||||||
|
@ -39,18 +39,18 @@ function hasCraft(state: any): state is { craft: string } {
|
||||||
return state && state.craft;
|
return state && state.craft;
|
||||||
}
|
}
|
||||||
export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
|
export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
|
||||||
const [alert, setAlert] = useState<Alert<AlwaysFiringParams> | null>(null);
|
const [alert, setAlert] = useState<Rule<AlwaysFiringParams> | null>(null);
|
||||||
const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
|
const [alertState, setAlertState] = useState<RuleTaskState | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!alert) {
|
if (!alert) {
|
||||||
http
|
http
|
||||||
.get<Alert<AlwaysFiringParams> | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`)
|
.get<Rule<AlwaysFiringParams> | null>(`${BASE_ALERTING_API_PATH}/rule/${id}`)
|
||||||
.then(setAlert);
|
.then(setAlert);
|
||||||
}
|
}
|
||||||
if (!alertState) {
|
if (!alertState) {
|
||||||
http
|
http
|
||||||
.get<RuleTaskState | null>(`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}/state`)
|
.get<RuleTaskState | null>(`${INTERNAL_BASE_ALERTING_API_PATH}/rule/${id}/state`)
|
||||||
.then(setAlertState);
|
.then(setAlertState);
|
||||||
}
|
}
|
||||||
}, [alert, alertState, http, id]);
|
}, [alert, alertState, http, id]);
|
||||||
|
@ -69,7 +69,7 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
|
||||||
<EuiText>
|
<EuiText>
|
||||||
<h2>Alerts</h2>
|
<h2>Alerts</h2>
|
||||||
</EuiText>
|
</EuiText>
|
||||||
{isEmpty(alertState.alertInstances) ? (
|
{isEmpty(alertState.alerts) ? (
|
||||||
<EuiCallOut title="No Alerts!" color="warning" iconType="help">
|
<EuiCallOut title="No Alerts!" color="warning" iconType="help">
|
||||||
<p>
|
<p>
|
||||||
The people in {alert.params.craft} at the moment <b>are not</b> {alert.params.op}{' '}
|
The people in {alert.params.craft} at the moment <b>are not</b> {alert.params.op}{' '}
|
||||||
|
@ -89,23 +89,21 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => {
|
||||||
<EuiFlexGroup>
|
<EuiFlexGroup>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiStat
|
<EuiStat
|
||||||
title={Object.keys(alertState.alertInstances ?? {}).length}
|
title={Object.keys(alertState.alerts ?? {}).length}
|
||||||
description={`People in ${alert.params.craft}`}
|
description={`People in ${alert.params.craft}`}
|
||||||
titleColor="primary"
|
titleColor="primary"
|
||||||
/>
|
/>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem>
|
<EuiFlexItem>
|
||||||
<EuiDescriptionList compressed>
|
<EuiDescriptionList compressed>
|
||||||
{Object.entries(alertState.alertInstances ?? {}).map(
|
{Object.entries(alertState.alerts ?? {}).map(([instance, { state }], index) => (
|
||||||
([instance, { state }], index) => (
|
<Fragment key={index}>
|
||||||
<Fragment key={index}>
|
<EuiDescriptionListTitle>{instance}</EuiDescriptionListTitle>
|
||||||
<EuiDescriptionListTitle>{instance}</EuiDescriptionListTitle>
|
<EuiDescriptionListDescription>
|
||||||
<EuiDescriptionListDescription>
|
{hasCraft(state) ? state.craft : 'Unknown Craft'}
|
||||||
{hasCraft(state) ? state.craft : 'Unknown Craft'}
|
</EuiDescriptionListDescription>
|
||||||
</EuiDescriptionListDescription>
|
</Fragment>
|
||||||
</Fragment>
|
))}
|
||||||
)
|
|
||||||
)}
|
|
||||||
</EuiDescriptionList>
|
</EuiDescriptionList>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
|
|
|
@ -8,6 +8,15 @@
|
||||||
import { LicenseType } from '../../licensing/common/types';
|
import { LicenseType } from '../../licensing/common/types';
|
||||||
import { RecoveredActionGroupId, DefaultActionGroupId } from './builtin_action_groups';
|
import { RecoveredActionGroupId, DefaultActionGroupId } from './builtin_action_groups';
|
||||||
|
|
||||||
|
interface ConsumerPrivileges {
|
||||||
|
read: boolean;
|
||||||
|
all: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ActionVariable {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
export interface RuleType<
|
export interface RuleType<
|
||||||
ActionGroupIds extends Exclude<string, RecoveredActionGroupId> = DefaultActionGroupId,
|
ActionGroupIds extends Exclude<string, RecoveredActionGroupId> = DefaultActionGroupId,
|
||||||
RecoveryActionGroupId extends string = RecoveredActionGroupId
|
RecoveryActionGroupId extends string = RecoveredActionGroupId
|
||||||
|
@ -16,7 +25,11 @@ export interface RuleType<
|
||||||
name: string;
|
name: string;
|
||||||
actionGroups: Array<ActionGroup<ActionGroupIds>>;
|
actionGroups: Array<ActionGroup<ActionGroupIds>>;
|
||||||
recoveryActionGroup: ActionGroup<RecoveryActionGroupId>;
|
recoveryActionGroup: ActionGroup<RecoveryActionGroupId>;
|
||||||
actionVariables: string[];
|
actionVariables: {
|
||||||
|
context: ActionVariable[];
|
||||||
|
state: ActionVariable[];
|
||||||
|
params: ActionVariable[];
|
||||||
|
};
|
||||||
defaultActionGroupId: ActionGroupIds;
|
defaultActionGroupId: ActionGroupIds;
|
||||||
producer: string;
|
producer: string;
|
||||||
minimumLicenseRequired: LicenseType;
|
minimumLicenseRequired: LicenseType;
|
||||||
|
@ -24,6 +37,8 @@ export interface RuleType<
|
||||||
ruleTaskTimeout?: string;
|
ruleTaskTimeout?: string;
|
||||||
defaultScheduleInterval?: string;
|
defaultScheduleInterval?: string;
|
||||||
minimumScheduleInterval?: string;
|
minimumScheduleInterval?: string;
|
||||||
|
enabledInLicense: boolean;
|
||||||
|
authorizedConsumers: Record<string, ConsumerPrivileges>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ActionGroup<ActionGroupIds extends string> {
|
export interface ActionGroup<ActionGroupIds extends string> {
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RuleType, RecoveredActionGroup } from '../common';
|
import { Alert, RuleType } from '../common';
|
||||||
import { httpServiceMock } from '../../../../src/core/public/mocks';
|
import { httpServiceMock } from '../../../../src/core/public/mocks';
|
||||||
import { loadAlert, loadAlertType, loadAlertTypes } from './alert_api';
|
import { loadAlert, loadAlertType, loadAlertTypes } from './alert_api';
|
||||||
import uuid from 'uuid';
|
|
||||||
|
|
||||||
const http = httpServiceMock.createStartContract();
|
const http = httpServiceMock.createStartContract();
|
||||||
|
|
||||||
|
@ -16,26 +15,63 @@ beforeEach(() => jest.resetAllMocks());
|
||||||
|
|
||||||
describe('loadAlertTypes', () => {
|
describe('loadAlertTypes', () => {
|
||||||
test('should call get alert types API', async () => {
|
test('should call get alert types API', async () => {
|
||||||
const resolvedValue: RuleType[] = [
|
http.get.mockResolvedValueOnce([getApiRuleType()]);
|
||||||
{
|
|
||||||
id: 'test',
|
|
||||||
name: 'Test',
|
|
||||||
actionVariables: ['var1'],
|
|
||||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
|
||||||
defaultActionGroupId: 'default',
|
|
||||||
minimumLicenseRequired: 'basic',
|
|
||||||
isExportable: true,
|
|
||||||
recoveryActionGroup: RecoveredActionGroup,
|
|
||||||
producer: 'alerts',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
http.get.mockResolvedValueOnce(resolvedValue);
|
|
||||||
|
|
||||||
const result = await loadAlertTypes({ http });
|
const result = await loadAlertTypes({ http });
|
||||||
expect(result).toEqual(resolvedValue);
|
expect(result).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"actionGroups": Array [
|
||||||
|
Object {
|
||||||
|
"id": "default",
|
||||||
|
"name": "Threshold met",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"actionVariables": Object {
|
||||||
|
"context": Array [
|
||||||
|
Object {
|
||||||
|
"description": "A pre-constructed message for the alert.",
|
||||||
|
"name": "message",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"params": Array [
|
||||||
|
Object {
|
||||||
|
"description": "An array of values to use as the threshold; \\"between\\" and \\"notBetween\\" require two values, the others require one.",
|
||||||
|
"name": "threshold",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"state": Array [
|
||||||
|
Object {
|
||||||
|
"description": "Example state variable",
|
||||||
|
"name": "example",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"authorizedConsumers": Object {
|
||||||
|
"alerts": Object {
|
||||||
|
"all": true,
|
||||||
|
"read": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"defaultActionGroupId": "default",
|
||||||
|
"enabledInLicense": true,
|
||||||
|
"id": ".index-threshold",
|
||||||
|
"isExportable": true,
|
||||||
|
"minimumLicenseRequired": "basic",
|
||||||
|
"name": "Index threshold",
|
||||||
|
"producer": "stackAlerts",
|
||||||
|
"recoveryActionGroup": Object {
|
||||||
|
"id": "recovered",
|
||||||
|
"name": "Recovered",
|
||||||
|
},
|
||||||
|
"ruleTaskTimeout": "5m",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
|
||||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
"/api/alerts/list_alert_types",
|
"/api/alerting/rule_types",
|
||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
@ -43,67 +79,256 @@ describe('loadAlertTypes', () => {
|
||||||
|
|
||||||
describe('loadAlertType', () => {
|
describe('loadAlertType', () => {
|
||||||
test('should call get alert types API', async () => {
|
test('should call get alert types API', async () => {
|
||||||
const alertType: RuleType = {
|
const ruleType = getApiRuleType();
|
||||||
id: 'test',
|
http.get.mockResolvedValueOnce([ruleType]);
|
||||||
name: 'Test',
|
|
||||||
actionVariables: ['var1'],
|
|
||||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
|
||||||
defaultActionGroupId: 'default',
|
|
||||||
minimumLicenseRequired: 'basic',
|
|
||||||
isExportable: true,
|
|
||||||
recoveryActionGroup: RecoveredActionGroup,
|
|
||||||
producer: 'alerts',
|
|
||||||
};
|
|
||||||
http.get.mockResolvedValueOnce([alertType]);
|
|
||||||
|
|
||||||
await loadAlertType({ http, id: alertType.id });
|
const result = await loadAlertType({ http, id: ruleType.id });
|
||||||
|
expect(result).toEqual(getRuleType());
|
||||||
expect(http.get.mock.calls[0]).toMatchInlineSnapshot(`
|
|
||||||
Array [
|
|
||||||
"/api/alerts/list_alert_types",
|
|
||||||
]
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should find the required alertType', async () => {
|
|
||||||
const alertType: RuleType = {
|
|
||||||
id: 'test-another',
|
|
||||||
name: 'Test Another',
|
|
||||||
actionVariables: [],
|
|
||||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
|
||||||
defaultActionGroupId: 'default',
|
|
||||||
minimumLicenseRequired: 'basic',
|
|
||||||
isExportable: true,
|
|
||||||
recoveryActionGroup: RecoveredActionGroup,
|
|
||||||
producer: 'alerts',
|
|
||||||
};
|
|
||||||
http.get.mockResolvedValueOnce([alertType]);
|
|
||||||
|
|
||||||
expect(await loadAlertType({ http, id: 'test-another' })).toEqual(alertType);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('loadAlert', () => {
|
describe('loadAlert', () => {
|
||||||
test('should call get API with base parameters', async () => {
|
test('should call get API with base parameters', async () => {
|
||||||
const alertId = uuid.v4();
|
const apiRule = getApiRule();
|
||||||
const resolvedValue = {
|
http.get.mockResolvedValueOnce(apiRule);
|
||||||
id: alertId,
|
|
||||||
name: 'name',
|
|
||||||
tags: [],
|
|
||||||
enabled: true,
|
|
||||||
alertTypeId: '.noop',
|
|
||||||
schedule: { interval: '1s' },
|
|
||||||
actions: [],
|
|
||||||
params: {},
|
|
||||||
createdBy: null,
|
|
||||||
updatedBy: null,
|
|
||||||
throttle: null,
|
|
||||||
muteAll: false,
|
|
||||||
mutedInstanceIds: [],
|
|
||||||
};
|
|
||||||
http.get.mockResolvedValueOnce(resolvedValue);
|
|
||||||
|
|
||||||
expect(await loadAlert({ http, alertId })).toEqual(resolvedValue);
|
const res = await loadAlert({ http, alertId: apiRule.id });
|
||||||
expect(http.get).toHaveBeenCalledWith(`/api/alerts/alert/${alertId}`);
|
expect(res).toEqual(getRule());
|
||||||
|
|
||||||
|
const fixedDate = new Date('2021-12-11T16:59:50.152Z');
|
||||||
|
res.updatedAt = fixedDate;
|
||||||
|
res.createdAt = fixedDate;
|
||||||
|
res.executionStatus.lastExecutionDate = fixedDate;
|
||||||
|
expect(res).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"actions": Array [
|
||||||
|
Object {
|
||||||
|
"actionTypeId": ".server-log",
|
||||||
|
"group": "threshold met",
|
||||||
|
"id": "3619a0d0-582b-11ec-8995-2b1578a3bc5d",
|
||||||
|
"params": Object {
|
||||||
|
"message": "alert 37: {{context.message}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"alertTypeId": ".index-threshold",
|
||||||
|
"apiKey": null,
|
||||||
|
"apiKeyOwner": "2889684073",
|
||||||
|
"consumer": "alerts",
|
||||||
|
"createdAt": 2021-12-11T16:59:50.152Z,
|
||||||
|
"createdBy": "elastic",
|
||||||
|
"enabled": true,
|
||||||
|
"executionStatus": Object {
|
||||||
|
"lastDuration": 1194,
|
||||||
|
"lastExecutionDate": 2021-12-11T16:59:50.152Z,
|
||||||
|
"status": "ok",
|
||||||
|
},
|
||||||
|
"id": "3d534c70-582b-11ec-8995-2b1578a3bc5d",
|
||||||
|
"muteAll": false,
|
||||||
|
"mutedInstanceIds": Array [],
|
||||||
|
"name": "stressing index-threshold 37/200",
|
||||||
|
"notifyWhen": "onActiveAlert",
|
||||||
|
"params": Object {
|
||||||
|
"x": 42,
|
||||||
|
},
|
||||||
|
"schedule": Object {
|
||||||
|
"interval": "1s",
|
||||||
|
},
|
||||||
|
"scheduledTaskId": "52125fb0-5895-11ec-ae69-bb65d1a71b72",
|
||||||
|
"tags": Array [],
|
||||||
|
"throttle": null,
|
||||||
|
"updatedAt": 2021-12-11T16:59:50.152Z,
|
||||||
|
"updatedBy": "2889684073",
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
expect(http.get).toHaveBeenCalledWith(`/api/alerting/rule/${apiRule.id}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getApiRuleType() {
|
||||||
|
return {
|
||||||
|
id: '.index-threshold',
|
||||||
|
name: 'Index threshold',
|
||||||
|
producer: 'stackAlerts',
|
||||||
|
enabled_in_license: true,
|
||||||
|
recovery_action_group: {
|
||||||
|
id: 'recovered',
|
||||||
|
name: 'Recovered',
|
||||||
|
},
|
||||||
|
action_groups: [
|
||||||
|
{
|
||||||
|
id: 'default',
|
||||||
|
name: 'Threshold met',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default_action_group_id: 'default',
|
||||||
|
minimum_license_required: 'basic',
|
||||||
|
is_exportable: true,
|
||||||
|
rule_task_timeout: '5m',
|
||||||
|
action_variables: {
|
||||||
|
context: [
|
||||||
|
{
|
||||||
|
name: 'message',
|
||||||
|
description: 'A pre-constructed message for the alert.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
name: 'example',
|
||||||
|
description: 'Example state variable',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'threshold',
|
||||||
|
description:
|
||||||
|
'An array of values to use as the threshold; "between" and "notBetween" require two values, the others require one.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
authorized_consumers: {
|
||||||
|
alerts: {
|
||||||
|
read: true,
|
||||||
|
all: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRuleType(): RuleType {
|
||||||
|
return {
|
||||||
|
id: '.index-threshold',
|
||||||
|
name: 'Index threshold',
|
||||||
|
producer: 'stackAlerts',
|
||||||
|
enabledInLicense: true,
|
||||||
|
recoveryActionGroup: {
|
||||||
|
id: 'recovered',
|
||||||
|
name: 'Recovered',
|
||||||
|
},
|
||||||
|
actionGroups: [
|
||||||
|
{
|
||||||
|
id: 'default',
|
||||||
|
name: 'Threshold met',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultActionGroupId: 'default',
|
||||||
|
minimumLicenseRequired: 'basic',
|
||||||
|
isExportable: true,
|
||||||
|
ruleTaskTimeout: '5m',
|
||||||
|
actionVariables: {
|
||||||
|
context: [
|
||||||
|
{
|
||||||
|
name: 'message',
|
||||||
|
description: 'A pre-constructed message for the alert.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
state: [
|
||||||
|
{
|
||||||
|
name: 'example',
|
||||||
|
description: 'Example state variable',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'threshold',
|
||||||
|
description:
|
||||||
|
'An array of values to use as the threshold; "between" and "notBetween" require two values, the others require one.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
authorizedConsumers: {
|
||||||
|
alerts: {
|
||||||
|
read: true,
|
||||||
|
all: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const DateNow = Date.now();
|
||||||
|
const RuleCreateDate = new Date(DateNow - 2000);
|
||||||
|
const RuleUpdateDate = new Date(DateNow - 1000);
|
||||||
|
const RuleExecuteDate = new Date(DateNow);
|
||||||
|
|
||||||
|
function getApiRule() {
|
||||||
|
return {
|
||||||
|
id: '3d534c70-582b-11ec-8995-2b1578a3bc5d',
|
||||||
|
notify_when: 'onActiveAlert',
|
||||||
|
rule_type_id: '.index-threshold',
|
||||||
|
name: 'stressing index-threshold 37/200',
|
||||||
|
consumer: 'alerts',
|
||||||
|
tags: [],
|
||||||
|
enabled: true,
|
||||||
|
throttle: null,
|
||||||
|
api_key: null,
|
||||||
|
api_key_owner: '2889684073',
|
||||||
|
created_by: 'elastic',
|
||||||
|
updated_by: '2889684073',
|
||||||
|
mute_all: false,
|
||||||
|
muted_alert_ids: [],
|
||||||
|
schedule: {
|
||||||
|
interval: '1s',
|
||||||
|
},
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
connector_type_id: '.server-log',
|
||||||
|
params: {
|
||||||
|
message: 'alert 37: {{context.message}}',
|
||||||
|
},
|
||||||
|
group: 'threshold met',
|
||||||
|
id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
params: { x: 42 },
|
||||||
|
updated_at: RuleUpdateDate.toISOString(),
|
||||||
|
created_at: RuleCreateDate.toISOString(),
|
||||||
|
scheduled_task_id: '52125fb0-5895-11ec-ae69-bb65d1a71b72',
|
||||||
|
execution_status: {
|
||||||
|
status: 'ok',
|
||||||
|
last_execution_date: RuleExecuteDate.toISOString(),
|
||||||
|
last_duration: 1194,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRule(): Alert<{ x: number }> {
|
||||||
|
return {
|
||||||
|
id: '3d534c70-582b-11ec-8995-2b1578a3bc5d',
|
||||||
|
notifyWhen: 'onActiveAlert',
|
||||||
|
alertTypeId: '.index-threshold',
|
||||||
|
name: 'stressing index-threshold 37/200',
|
||||||
|
consumer: 'alerts',
|
||||||
|
tags: [],
|
||||||
|
enabled: true,
|
||||||
|
throttle: null,
|
||||||
|
apiKey: null,
|
||||||
|
apiKeyOwner: '2889684073',
|
||||||
|
createdBy: 'elastic',
|
||||||
|
updatedBy: '2889684073',
|
||||||
|
muteAll: false,
|
||||||
|
mutedInstanceIds: [],
|
||||||
|
schedule: {
|
||||||
|
interval: '1s',
|
||||||
|
},
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionTypeId: '.server-log',
|
||||||
|
params: {
|
||||||
|
message: 'alert 37: {{context.message}}',
|
||||||
|
},
|
||||||
|
group: 'threshold met',
|
||||||
|
id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
params: { x: 42 },
|
||||||
|
updatedAt: RuleUpdateDate,
|
||||||
|
createdAt: RuleCreateDate,
|
||||||
|
scheduledTaskId: '52125fb0-5895-11ec-ae69-bb65d1a71b72',
|
||||||
|
executionStatus: {
|
||||||
|
status: 'ok',
|
||||||
|
lastExecutionDate: RuleExecuteDate,
|
||||||
|
lastDuration: 1194,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -6,11 +6,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { HttpSetup } from 'kibana/public';
|
import { HttpSetup } from 'kibana/public';
|
||||||
import { LEGACY_BASE_ALERT_API_PATH } from '../common';
|
import { BASE_ALERTING_API_PATH } from '../common';
|
||||||
import type { Alert, RuleType } from '../common';
|
import type { Alert, RuleType } from '../common';
|
||||||
|
import { AsApiContract } from '../../actions/common';
|
||||||
|
import { transformAlert, transformRuleType, ApiAlert } from './lib/common_transformations';
|
||||||
|
|
||||||
export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise<RuleType[]> {
|
export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise<RuleType[]> {
|
||||||
return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`);
|
const res = await http.get<Array<AsApiContract<RuleType>>>(
|
||||||
|
`${BASE_ALERTING_API_PATH}/rule_types`
|
||||||
|
);
|
||||||
|
return res.map((ruleType) => transformRuleType(ruleType));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadAlertType({
|
export async function loadAlertType({
|
||||||
|
@ -20,10 +25,8 @@ export async function loadAlertType({
|
||||||
http: HttpSetup;
|
http: HttpSetup;
|
||||||
id: RuleType['id'];
|
id: RuleType['id'];
|
||||||
}): Promise<RuleType | undefined> {
|
}): Promise<RuleType | undefined> {
|
||||||
const alertTypes = (await http.get(
|
const ruleTypes = await loadAlertTypes({ http });
|
||||||
`${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`
|
return ruleTypes.find((type) => type.id === id);
|
||||||
)) as RuleType[];
|
|
||||||
return alertTypes.find((type) => type.id === id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadAlert({
|
export async function loadAlert({
|
||||||
|
@ -33,5 +36,6 @@ export async function loadAlert({
|
||||||
http: HttpSetup;
|
http: HttpSetup;
|
||||||
alertId: string;
|
alertId: string;
|
||||||
}): Promise<Alert> {
|
}): Promise<Alert> {
|
||||||
return await http.get(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alertId}`);
|
const res = await http.get<ApiAlert>(`${BASE_ALERTING_API_PATH}/rule/${alertId}`);
|
||||||
|
return transformAlert(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,17 @@ const mockAlertType = (id: string): RuleType => ({
|
||||||
name: id,
|
name: id,
|
||||||
actionGroups: [],
|
actionGroups: [],
|
||||||
recoveryActionGroup: RecoveredActionGroup,
|
recoveryActionGroup: RecoveredActionGroup,
|
||||||
actionVariables: [],
|
actionVariables: {
|
||||||
|
context: [],
|
||||||
|
state: [],
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
defaultActionGroupId: 'default',
|
defaultActionGroupId: 'default',
|
||||||
producer: 'alerts',
|
producer: 'alerts',
|
||||||
minimumLicenseRequired: 'basic',
|
minimumLicenseRequired: 'basic',
|
||||||
isExportable: true,
|
isExportable: true,
|
||||||
|
enabledInLicense: true,
|
||||||
|
authorizedConsumers: { foo: { read: true, all: true } },
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('AlertNavigationRegistry', () => {
|
describe('AlertNavigationRegistry', () => {
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* 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 { ApiAlert, transformAlert } from './common_transformations';
|
||||||
|
import { AlertExecutionStatusErrorReasons } from '../../common';
|
||||||
|
|
||||||
|
beforeEach(() => jest.resetAllMocks());
|
||||||
|
|
||||||
|
const dateFixed = Date.parse('2021-12-15T12:34:56.789Z');
|
||||||
|
const dateCreated = new Date(dateFixed - 2000);
|
||||||
|
const dateUpdated = new Date(dateFixed - 1000);
|
||||||
|
const dateExecuted = new Date(dateFixed);
|
||||||
|
|
||||||
|
describe('common_transformations', () => {
|
||||||
|
test('transformAlert() with all optional fields', () => {
|
||||||
|
const apiAlert: ApiAlert = {
|
||||||
|
id: 'some-id',
|
||||||
|
name: 'some-name',
|
||||||
|
enabled: true,
|
||||||
|
tags: ['tag-1', 'tag-2'],
|
||||||
|
rule_type_id: 'some-rule-type',
|
||||||
|
consumer: 'some-consumer',
|
||||||
|
schedule: { interval: '1s' },
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
connector_type_id: 'some-connector-type-id',
|
||||||
|
group: 'some group',
|
||||||
|
id: 'some-connector-id',
|
||||||
|
params: { foo: 'car', bar: [1, 2, 3] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
params: { bar: 'foo', numbers: { 1: [2, 3] } } as never,
|
||||||
|
scheduled_task_id: 'some-task-id',
|
||||||
|
created_by: 'created-by-user',
|
||||||
|
updated_by: null,
|
||||||
|
created_at: dateCreated.toISOString(),
|
||||||
|
updated_at: dateUpdated.toISOString(),
|
||||||
|
api_key: 'some-api-key',
|
||||||
|
api_key_owner: 'api-key-user',
|
||||||
|
throttle: '2s',
|
||||||
|
notify_when: 'onActiveAlert',
|
||||||
|
mute_all: false,
|
||||||
|
muted_alert_ids: ['bob', 'jim'],
|
||||||
|
execution_status: {
|
||||||
|
last_execution_date: dateExecuted.toISOString(),
|
||||||
|
last_duration: 42,
|
||||||
|
status: 'error',
|
||||||
|
error: {
|
||||||
|
reason: AlertExecutionStatusErrorReasons.Unknown,
|
||||||
|
message: 'this is just a test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(transformAlert(apiAlert)).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"actions": Array [
|
||||||
|
Object {
|
||||||
|
"actionTypeId": "some-connector-type-id",
|
||||||
|
"group": "some group",
|
||||||
|
"id": "some-connector-id",
|
||||||
|
"params": Object {
|
||||||
|
"bar": Array [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
"foo": "car",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"alertTypeId": "some-rule-type",
|
||||||
|
"apiKey": "some-api-key",
|
||||||
|
"apiKeyOwner": "api-key-user",
|
||||||
|
"consumer": "some-consumer",
|
||||||
|
"createdAt": 2021-12-15T12:34:54.789Z,
|
||||||
|
"createdBy": "created-by-user",
|
||||||
|
"enabled": true,
|
||||||
|
"executionStatus": Object {
|
||||||
|
"error": Object {
|
||||||
|
"message": "this is just a test",
|
||||||
|
"reason": "unknown",
|
||||||
|
},
|
||||||
|
"lastDuration": 42,
|
||||||
|
"lastExecutionDate": 2021-12-15T12:34:56.789Z,
|
||||||
|
"status": "error",
|
||||||
|
},
|
||||||
|
"id": "some-id",
|
||||||
|
"muteAll": false,
|
||||||
|
"mutedInstanceIds": Array [
|
||||||
|
"bob",
|
||||||
|
"jim",
|
||||||
|
],
|
||||||
|
"name": "some-name",
|
||||||
|
"notifyWhen": "onActiveAlert",
|
||||||
|
"params": Object {
|
||||||
|
"bar": "foo",
|
||||||
|
"numbers": Object {
|
||||||
|
"1": Array [
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"schedule": Object {
|
||||||
|
"interval": "1s",
|
||||||
|
},
|
||||||
|
"scheduledTaskId": "some-task-id",
|
||||||
|
"tags": Array [
|
||||||
|
"tag-1",
|
||||||
|
"tag-2",
|
||||||
|
],
|
||||||
|
"throttle": "2s",
|
||||||
|
"updatedAt": 2021-12-15T12:34:55.789Z,
|
||||||
|
"updatedBy": null,
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('transformAlert() with no optional fields', () => {
|
||||||
|
const apiAlert: ApiAlert = {
|
||||||
|
id: 'some-id',
|
||||||
|
name: 'some-name',
|
||||||
|
enabled: true,
|
||||||
|
tags: [],
|
||||||
|
rule_type_id: 'some-rule-type',
|
||||||
|
consumer: 'some-consumer',
|
||||||
|
schedule: { interval: '1s' },
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
connector_type_id: 'some-connector-type-id',
|
||||||
|
group: 'some group',
|
||||||
|
id: 'some-connector-id',
|
||||||
|
params: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
params: {} as never,
|
||||||
|
created_by: 'created-by-user',
|
||||||
|
updated_by: null,
|
||||||
|
created_at: dateCreated.toISOString(),
|
||||||
|
updated_at: dateUpdated.toISOString(),
|
||||||
|
api_key: 'some-api-key',
|
||||||
|
api_key_owner: 'api-key-user',
|
||||||
|
throttle: '2s',
|
||||||
|
notify_when: 'onActiveAlert',
|
||||||
|
mute_all: false,
|
||||||
|
muted_alert_ids: ['bob', 'jim'],
|
||||||
|
execution_status: {
|
||||||
|
last_execution_date: dateExecuted.toISOString(),
|
||||||
|
status: 'error',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(transformAlert(apiAlert)).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"actions": Array [
|
||||||
|
Object {
|
||||||
|
"actionTypeId": "some-connector-type-id",
|
||||||
|
"group": "some group",
|
||||||
|
"id": "some-connector-id",
|
||||||
|
"params": Object {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"alertTypeId": "some-rule-type",
|
||||||
|
"apiKey": "some-api-key",
|
||||||
|
"apiKeyOwner": "api-key-user",
|
||||||
|
"consumer": "some-consumer",
|
||||||
|
"createdAt": 2021-12-15T12:34:54.789Z,
|
||||||
|
"createdBy": "created-by-user",
|
||||||
|
"enabled": true,
|
||||||
|
"executionStatus": Object {
|
||||||
|
"lastDuration": undefined,
|
||||||
|
"lastExecutionDate": 2021-12-15T12:34:56.789Z,
|
||||||
|
"status": "error",
|
||||||
|
},
|
||||||
|
"id": "some-id",
|
||||||
|
"muteAll": false,
|
||||||
|
"mutedInstanceIds": Array [
|
||||||
|
"bob",
|
||||||
|
"jim",
|
||||||
|
],
|
||||||
|
"name": "some-name",
|
||||||
|
"notifyWhen": "onActiveAlert",
|
||||||
|
"params": Object {},
|
||||||
|
"schedule": Object {
|
||||||
|
"interval": "1s",
|
||||||
|
},
|
||||||
|
"scheduledTaskId": undefined,
|
||||||
|
"tags": Array [],
|
||||||
|
"throttle": "2s",
|
||||||
|
"updatedAt": 2021-12-15T12:34:55.789Z,
|
||||||
|
"updatedBy": null,
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
111
x-pack/plugins/alerting/public/lib/common_transformations.ts
Normal file
111
x-pack/plugins/alerting/public/lib/common_transformations.ts
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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 { AlertExecutionStatus, Alert, AlertAction, RuleType } from '../../common';
|
||||||
|
import { AsApiContract } from '../../../actions/common';
|
||||||
|
|
||||||
|
function transformAction(input: AsApiContract<AlertAction>): AlertAction {
|
||||||
|
const { connector_type_id: actionTypeId, ...rest } = input;
|
||||||
|
return { actionTypeId, ...rest };
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsApiContract does not deal with object properties that are dates - the
|
||||||
|
// API version needs to be a string, and the non-API version needs to be a Date
|
||||||
|
type ApiAlertExecutionStatus = Omit<AsApiContract<AlertExecutionStatus>, 'last_execution_date'> & {
|
||||||
|
last_execution_date: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function transformExecutionStatus(input: ApiAlertExecutionStatus): AlertExecutionStatus {
|
||||||
|
const { last_execution_date: lastExecutionDate, last_duration: lastDuration, ...rest } = input;
|
||||||
|
return {
|
||||||
|
lastExecutionDate: new Date(lastExecutionDate),
|
||||||
|
lastDuration,
|
||||||
|
...rest,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsApiContract does not deal with object properties that also
|
||||||
|
// need snake -> camel conversion, Dates, are renamed, etc, so we do by hand
|
||||||
|
export type ApiAlert = Omit<
|
||||||
|
AsApiContract<Alert>,
|
||||||
|
| 'execution_status'
|
||||||
|
| 'actions'
|
||||||
|
| 'created_at'
|
||||||
|
| 'updated_at'
|
||||||
|
| 'alert_type_id'
|
||||||
|
| 'muted_instance_ids'
|
||||||
|
> & {
|
||||||
|
execution_status: ApiAlertExecutionStatus;
|
||||||
|
actions: Array<AsApiContract<AlertAction>>;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
rule_type_id: string;
|
||||||
|
muted_alert_ids: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function transformAlert(input: ApiAlert): Alert {
|
||||||
|
const {
|
||||||
|
rule_type_id: alertTypeId,
|
||||||
|
created_by: createdBy,
|
||||||
|
updated_by: updatedBy,
|
||||||
|
created_at: createdAt,
|
||||||
|
updated_at: updatedAt,
|
||||||
|
api_key: apiKey,
|
||||||
|
api_key_owner: apiKeyOwner,
|
||||||
|
notify_when: notifyWhen,
|
||||||
|
mute_all: muteAll,
|
||||||
|
muted_alert_ids: mutedInstanceIds,
|
||||||
|
scheduled_task_id: scheduledTaskId,
|
||||||
|
execution_status: executionStatusAPI,
|
||||||
|
actions: actionsAPI,
|
||||||
|
...rest
|
||||||
|
} = input;
|
||||||
|
|
||||||
|
return {
|
||||||
|
alertTypeId,
|
||||||
|
createdBy,
|
||||||
|
updatedBy,
|
||||||
|
createdAt: new Date(createdAt),
|
||||||
|
updatedAt: new Date(updatedAt),
|
||||||
|
apiKey,
|
||||||
|
apiKeyOwner,
|
||||||
|
notifyWhen,
|
||||||
|
muteAll,
|
||||||
|
mutedInstanceIds,
|
||||||
|
executionStatus: transformExecutionStatus(executionStatusAPI),
|
||||||
|
actions: actionsAPI ? actionsAPI.map((action) => transformAction(action)) : [],
|
||||||
|
scheduledTaskId,
|
||||||
|
...rest,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transformRuleType(input: AsApiContract<RuleType>): RuleType {
|
||||||
|
const {
|
||||||
|
recovery_action_group: recoveryActionGroup,
|
||||||
|
action_groups: actionGroups,
|
||||||
|
default_action_group_id: defaultActionGroupId,
|
||||||
|
minimum_license_required: minimumLicenseRequired,
|
||||||
|
action_variables: actionVariables,
|
||||||
|
rule_task_timeout: ruleTaskTimeout,
|
||||||
|
is_exportable: isExportable,
|
||||||
|
authorized_consumers: authorizedConsumers,
|
||||||
|
enabled_in_license: enabledInLicense,
|
||||||
|
...rest
|
||||||
|
} = input;
|
||||||
|
|
||||||
|
return {
|
||||||
|
recoveryActionGroup,
|
||||||
|
actionGroups,
|
||||||
|
defaultActionGroupId,
|
||||||
|
minimumLicenseRequired,
|
||||||
|
actionVariables,
|
||||||
|
ruleTaskTimeout,
|
||||||
|
isExportable,
|
||||||
|
authorizedConsumers,
|
||||||
|
enabledInLicense,
|
||||||
|
...rest,
|
||||||
|
};
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSwitch } from '@elastic/eui';
|
||||||
import { CommonAlert } from '../../common/types/alerts';
|
import { CommonAlert } from '../../common/types/alerts';
|
||||||
import { Legacy } from '../legacy_shims';
|
import { Legacy } from '../legacy_shims';
|
||||||
import { hideBottomBar, showBottomBar } from '../lib/setup_mode';
|
import { hideBottomBar, showBottomBar } from '../lib/setup_mode';
|
||||||
import { LEGACY_BASE_ALERT_API_PATH } from '../../../alerting/common';
|
import { BASE_ALERTING_API_PATH } from '../../../alerting/common';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
alert: CommonAlert;
|
alert: CommonAlert;
|
||||||
|
@ -28,7 +28,7 @@ export const AlertConfiguration: React.FC<Props> = (props: Props) => {
|
||||||
async function disableAlert() {
|
async function disableAlert() {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
try {
|
try {
|
||||||
await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_disable`);
|
await Legacy.shims.http.post(`${BASE_ALERTING_API_PATH}/rule/${alert.id}/_disable`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Legacy.shims.toastNotifications.addDanger({
|
Legacy.shims.toastNotifications.addDanger({
|
||||||
title: i18n.translate('xpack.monitoring.alerts.panel.disableAlert.errorTitle', {
|
title: i18n.translate('xpack.monitoring.alerts.panel.disableAlert.errorTitle', {
|
||||||
|
@ -42,7 +42,7 @@ export const AlertConfiguration: React.FC<Props> = (props: Props) => {
|
||||||
async function enableAlert() {
|
async function enableAlert() {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
try {
|
try {
|
||||||
await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_enable`);
|
await Legacy.shims.http.post(`${BASE_ALERTING_API_PATH}/rule/${alert.id}/_enable`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Legacy.shims.toastNotifications.addDanger({
|
Legacy.shims.toastNotifications.addDanger({
|
||||||
title: i18n.translate('xpack.monitoring.alerts.panel.enableAlert.errorTitle', {
|
title: i18n.translate('xpack.monitoring.alerts.panel.enableAlert.errorTitle', {
|
||||||
|
@ -56,7 +56,7 @@ export const AlertConfiguration: React.FC<Props> = (props: Props) => {
|
||||||
async function muteAlert() {
|
async function muteAlert() {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
try {
|
try {
|
||||||
await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_mute_all`);
|
await Legacy.shims.http.post(`${BASE_ALERTING_API_PATH}/rule/${alert.id}/_mute_all`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Legacy.shims.toastNotifications.addDanger({
|
Legacy.shims.toastNotifications.addDanger({
|
||||||
title: i18n.translate('xpack.monitoring.alerts.panel.muteAlert.errorTitle', {
|
title: i18n.translate('xpack.monitoring.alerts.panel.muteAlert.errorTitle', {
|
||||||
|
@ -70,7 +70,7 @@ export const AlertConfiguration: React.FC<Props> = (props: Props) => {
|
||||||
async function unmuteAlert() {
|
async function unmuteAlert() {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
try {
|
try {
|
||||||
await Legacy.shims.http.post(`${LEGACY_BASE_ALERT_API_PATH}/alert/${alert.id}/_unmute_all`);
|
await Legacy.shims.http.post(`${BASE_ALERTING_API_PATH}/rule/${alert.id}/_unmute_all`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Legacy.shims.toastNotifications.addDanger({
|
Legacy.shims.toastNotifications.addDanger({
|
||||||
title: i18n.translate('xpack.monitoring.alerts.panel.ummuteAlert.errorTitle', {
|
title: i18n.translate('xpack.monitoring.alerts.panel.ummuteAlert.errorTitle', {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue