mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Synthetics] Settings add config to enable default rules (#190800)
## Summary Settings add config to enable default rules !! separated out of https://github.com/elastic/kibana/pull/186585 !! <img width="1725" alt="image" src="https://github.com/user-attachments/assets/3fc18d13-d0fe-4f08-8e19-ae43fcb83228"> --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Dominique Belcher <dominique.clarke@elastic.co>
This commit is contained in:
parent
9653d7e1fc
commit
20ccb21c94
34 changed files with 382 additions and 140 deletions
|
@ -16,4 +16,6 @@ export const DYNAMIC_SETTINGS_DEFAULTS: DynamicSettings = {
|
|||
cc: [],
|
||||
bcc: [],
|
||||
},
|
||||
defaultTLSRuleEnabled: true,
|
||||
defaultStatusRuleEnabled: true,
|
||||
};
|
||||
|
|
|
@ -34,6 +34,8 @@ export const DynamicSettingsCodec = t.intersection([
|
|||
}),
|
||||
t.partial({
|
||||
defaultEmail: DefaultEmailCodec,
|
||||
defaultTLSRuleEnabled: t.boolean,
|
||||
defaultStatusRuleEnabled: t.boolean,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export const OverviewPendingStatusMetaDataCodec = t.intersection([
|
|||
monitorQueryId: t.string,
|
||||
configId: t.string,
|
||||
status: t.string,
|
||||
location: t.string,
|
||||
locationId: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
timestamp: t.string,
|
||||
|
|
|
@ -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 { SanitizedRule, SanitizedRuleAction, RuleSystemAction } from '@kbn/alerting-plugin/common';
|
||||
import { SYNTHETICS_STATUS_RULE, SYNTHETICS_TLS_RULE } from '../constants/synthetics_alerts';
|
||||
|
||||
export type DefaultRuleType = typeof SYNTHETICS_STATUS_RULE | typeof SYNTHETICS_TLS_RULE;
|
||||
type SYNTHETICS_DEFAULT_RULE = Omit<SanitizedRule<{}>, 'systemActions' | 'actions'> & {
|
||||
actions: Array<SanitizedRuleAction | RuleSystemAction>;
|
||||
ruleTypeId: SanitizedRule['alertTypeId'];
|
||||
};
|
||||
|
||||
export interface DEFAULT_ALERT_RESPONSE {
|
||||
statusRule: SYNTHETICS_DEFAULT_RULE | null;
|
||||
tlsRule: SYNTHETICS_DEFAULT_RULE | null;
|
||||
}
|
|
@ -7,3 +7,4 @@
|
|||
|
||||
export * from './synthetics_monitor';
|
||||
export * from './monitor_validation';
|
||||
export * from './default_alerts';
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
} from '../../../state';
|
||||
import { ClientPluginsStart } from '../../../../../plugin';
|
||||
|
||||
export const useSyntheticsAlert = (isOpen: boolean) => {
|
||||
export const useSyntheticsRules = (isOpen: boolean) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const defaultRules = useSelector(selectSyntheticsAlerts);
|
||||
|
@ -64,14 +64,15 @@ export const useSyntheticsAlert = (isOpen: boolean) => {
|
|||
const { triggersActionsUi } = useKibana<ClientPluginsStart>().services;
|
||||
|
||||
const EditAlertFlyout = useMemo(() => {
|
||||
if (!defaultRules) {
|
||||
const initialRule =
|
||||
alertFlyoutVisible === SYNTHETICS_TLS_RULE ? defaultRules?.tlsRule : defaultRules?.statusRule;
|
||||
if (!initialRule) {
|
||||
return null;
|
||||
}
|
||||
return triggersActionsUi.getEditRuleFlyout({
|
||||
onClose: () => dispatch(setAlertFlyoutVisible(null)),
|
||||
hideInterval: true,
|
||||
initialRule:
|
||||
alertFlyoutVisible === SYNTHETICS_TLS_RULE ? defaultRules.tlsRule : defaultRules.statusRule,
|
||||
initialRule,
|
||||
});
|
||||
}, [defaultRules, dispatch, triggersActionsUi, alertFlyoutVisible]);
|
||||
|
|
@ -26,7 +26,7 @@ import {
|
|||
import { ManageRulesLink } from '../common/links/manage_rules_link';
|
||||
import { ClientPluginsStart } from '../../../../plugin';
|
||||
import { ToggleFlyoutTranslations } from './hooks/translations';
|
||||
import { useSyntheticsAlert } from './hooks/use_synthetics_alert';
|
||||
import { useSyntheticsRules } from './hooks/use_synthetics_rules';
|
||||
import {
|
||||
selectAlertFlyoutVisibility,
|
||||
selectMonitorListState,
|
||||
|
@ -40,7 +40,7 @@ export const ToggleAlertFlyoutButton = () => {
|
|||
const { application } = useKibana<ClientPluginsStart>().services;
|
||||
const hasUptimeWrite = application?.capabilities.uptime?.save ?? false;
|
||||
|
||||
const { EditAlertFlyout, loading } = useSyntheticsAlert(isOpen);
|
||||
const { EditAlertFlyout, loading } = useSyntheticsRules(isOpen);
|
||||
|
||||
const { loaded, data: monitors } = useSelector(selectMonitorListState);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
EuiFlexItem,
|
||||
EuiForm,
|
||||
EuiSpacer,
|
||||
EuiSwitch,
|
||||
} from '@elastic/eui';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
|
@ -80,6 +81,50 @@ export const AlertDefaultsForm = () => {
|
|||
|
||||
return (
|
||||
<EuiForm>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.settings.defaultConnectors"
|
||||
defaultMessage="Default rules"
|
||||
/>
|
||||
</h4>
|
||||
}
|
||||
description={
|
||||
<FormattedMessage
|
||||
id="xpack.synthetics.settings.defaultConnectors.description"
|
||||
defaultMessage="Default rules are automatically created. You can disable creation of default rules here."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiSwitch
|
||||
label={i18n.translate('xpack.synthetics.ruleStatusDefaultsForm.euiSwitch.enabledLabel', {
|
||||
defaultMessage: 'Status rule enabled',
|
||||
})}
|
||||
checked={formFields?.defaultStatusRuleEnabled ?? true}
|
||||
onChange={() => {
|
||||
setFormFields({
|
||||
...formFields,
|
||||
defaultStatusRuleEnabled: !(formFields.defaultStatusRuleEnabled ?? true),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiSwitch
|
||||
label={i18n.translate('xpack.synthetics.ruleTLSDefaultsForm.euiSwitch.enabledLabel', {
|
||||
defaultMessage: 'TLS rule enabled',
|
||||
})}
|
||||
checked={formFields?.defaultTLSRuleEnabled ?? true}
|
||||
onChange={() => {
|
||||
setFormFields({
|
||||
...formFields,
|
||||
defaultTLSRuleEnabled: !(formFields.defaultTLSRuleEnabled ?? true),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</EuiDescribedFormGroup>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
|
|
|
@ -154,7 +154,7 @@ describe('useMonitorsSortedByStatus', () => {
|
|||
[`test-monitor-4-${location1.id}`]: {
|
||||
configId: 'test-monitor-4',
|
||||
monitorQueryId: 'test-monitor-4',
|
||||
location: location1.id,
|
||||
locationId: location1.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -5,24 +5,21 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Rule } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { DEFAULT_ALERT_RESPONSE } from '../../../../../common/types/default_alerts';
|
||||
import { createAsyncAction } from '../utils/actions';
|
||||
|
||||
export const getDefaultAlertingAction = createAsyncAction<
|
||||
void,
|
||||
{ statusRule: Rule; tlsRule: Rule }
|
||||
>('getDefaultAlertingAction');
|
||||
export const getDefaultAlertingAction = createAsyncAction<void, DEFAULT_ALERT_RESPONSE>(
|
||||
'getDefaultAlertingAction'
|
||||
);
|
||||
|
||||
export const enableDefaultAlertingAction = createAsyncAction<
|
||||
void,
|
||||
{ statusRule: Rule; tlsRule: Rule }
|
||||
>('enableDefaultAlertingAction');
|
||||
export const enableDefaultAlertingAction = createAsyncAction<void, DEFAULT_ALERT_RESPONSE>(
|
||||
'enableDefaultAlertingAction'
|
||||
);
|
||||
|
||||
export const enableDefaultAlertingSilentlyAction = createAsyncAction<
|
||||
void,
|
||||
{ statusRule: Rule; tlsRule: Rule }
|
||||
>('enableDefaultAlertingSilentlyAction');
|
||||
export const enableDefaultAlertingSilentlyAction = createAsyncAction<void, DEFAULT_ALERT_RESPONSE>(
|
||||
'enableDefaultAlertingSilentlyAction'
|
||||
);
|
||||
|
||||
export const updateDefaultAlertingAction = createAsyncAction<void, Rule>(
|
||||
export const updateDefaultAlertingAction = createAsyncAction<void, DEFAULT_ALERT_RESPONSE>(
|
||||
'updateDefaultAlertingAction'
|
||||
);
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Rule } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { SYNTHETICS_API_URLS } from '../../../../../common/constants';
|
||||
import { DEFAULT_ALERT_RESPONSE } from '../../../../../common/types/default_alerts';
|
||||
import { apiService } from '../../../../utils/api_service';
|
||||
|
||||
export async function getDefaultAlertingAPI(): Promise<{ statusRule: Rule; tlsRule: Rule }> {
|
||||
export async function getDefaultAlertingAPI(): Promise<DEFAULT_ALERT_RESPONSE> {
|
||||
return apiService.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING);
|
||||
}
|
||||
|
||||
export async function enableDefaultAlertingAPI(): Promise<{ statusRule: Rule; tlsRule: Rule }> {
|
||||
export async function enableDefaultAlertingAPI(): Promise<DEFAULT_ALERT_RESPONSE> {
|
||||
return apiService.post(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING);
|
||||
}
|
||||
|
||||
export async function updateDefaultAlertingAPI(): Promise<Rule> {
|
||||
export async function updateDefaultAlertingAPI(): Promise<DEFAULT_ALERT_RESPONSE> {
|
||||
return apiService.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
import { Rule } from '@kbn/triggers-actions-ui-plugin/public';
|
||||
import { DEFAULT_ALERT_RESPONSE } from '../../../../../common/types/default_alerts';
|
||||
import { IHttpSerializedFetchError } from '..';
|
||||
import {
|
||||
enableDefaultAlertingAction,
|
||||
|
@ -16,7 +16,7 @@ import {
|
|||
} from './actions';
|
||||
|
||||
export interface DefaultAlertingState {
|
||||
data?: { statusRule: Rule; tlsRule: Rule };
|
||||
data?: DEFAULT_ALERT_RESPONSE;
|
||||
success: boolean | null;
|
||||
loading: boolean;
|
||||
error: IHttpSerializedFetchError | null;
|
||||
|
|
|
@ -36,9 +36,17 @@ export const getDynamicSettings = async (): Promise<DynamicSettings> => {
|
|||
export const setDynamicSettings = async ({
|
||||
settings,
|
||||
}: SaveApiRequest): Promise<DynamicSettingsSaveResponse> => {
|
||||
const newSettings: DynamicSettings = {
|
||||
certAgeThreshold: settings.certAgeThreshold,
|
||||
certExpirationThreshold: settings.certExpirationThreshold,
|
||||
defaultConnectors: settings.defaultConnectors,
|
||||
defaultEmail: settings.defaultEmail,
|
||||
defaultTLSRuleEnabled: settings.defaultTLSRuleEnabled,
|
||||
defaultStatusRuleEnabled: settings.defaultStatusRuleEnabled,
|
||||
};
|
||||
return await apiService.put(
|
||||
SYNTHETICS_API_URLS.DYNAMIC_SETTINGS,
|
||||
settings,
|
||||
newSettings,
|
||||
DynamicSettingsSaveCodec,
|
||||
{
|
||||
version: '2023-10-31',
|
||||
|
|
|
@ -274,6 +274,7 @@ describe('setRecoveredAlertsContext', () => {
|
|||
alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id',
|
||||
monitorName: 'test-monitor',
|
||||
recoveryReason: 'the monitor has been deleted',
|
||||
'kibana.alert.reason': 'the monitor has been deleted',
|
||||
recoveryStatus: 'has been deleted',
|
||||
monitorUrl: '(unavailable)',
|
||||
monitorUrlLabel: 'URL',
|
||||
|
@ -350,6 +351,7 @@ describe('setRecoveredAlertsContext', () => {
|
|||
alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id',
|
||||
monitorName: 'test-monitor',
|
||||
recoveryReason: 'this location has been removed from the monitor',
|
||||
'kibana.alert.reason': 'this location has been removed from the monitor',
|
||||
recoveryStatus: 'has recovered',
|
||||
stateId: '123456',
|
||||
status: 'recovered',
|
||||
|
@ -421,6 +423,8 @@ describe('setRecoveredAlertsContext', () => {
|
|||
status: 'up',
|
||||
recoveryReason:
|
||||
'the monitor is now up again. It ran successfully at Feb 26, 2023 @ 00:00:00.000',
|
||||
'kibana.alert.reason':
|
||||
'the monitor is now up again. It ran successfully at Feb 26, 2023 @ 00:00:00.000',
|
||||
recoveryStatus: 'is now up',
|
||||
locationId: location,
|
||||
checkedAt: 'Feb 26, 2023 @ 00:00:00.000',
|
||||
|
|
|
@ -19,6 +19,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
|
||||
import { legacyExperimentalFieldMap, ObservabilityUptimeAlert } from '@kbn/alerts-as-data-utils';
|
||||
import { PublicAlertsClient } from '@kbn/alerting-plugin/server/alerts_client/types';
|
||||
import { ALERT_REASON } from '@kbn/rule-data-utils';
|
||||
import { syntheticsRuleFieldMap } from '../../common/rules/synthetics_rule_field_map';
|
||||
import { combineFiltersAndUserSearch, stringifyKueries } from '../../common/lib';
|
||||
import {
|
||||
|
@ -298,6 +299,7 @@ export const setRecoveredAlertsContext = ({
|
|||
linkMessage,
|
||||
...(isUp ? { status: 'up' } : {}),
|
||||
...(recoveryReason ? { [RECOVERY_REASON]: recoveryReason } : {}),
|
||||
...(recoveryReason ? { [ALERT_REASON]: recoveryReason } : {}),
|
||||
...(basePath && spaceId && alertUuid
|
||||
? { [ALERT_DETAILS_URL]: getAlertDetailsUrl(basePath, spaceId, alertUuid) }
|
||||
: {}),
|
||||
|
|
|
@ -79,7 +79,7 @@ export class StatusRuleExecutor {
|
|||
monitorLocationMap,
|
||||
projectMonitorsCount,
|
||||
monitorQueryIdToConfigIdMap,
|
||||
} = processMonitors(this.monitors, this.server, this.soClient, this.syntheticsMonitorClient);
|
||||
} = processMonitors(this.monitors);
|
||||
|
||||
return {
|
||||
enabledMonitorQueryIds,
|
||||
|
|
|
@ -74,7 +74,7 @@ export class TLSRuleExecutor {
|
|||
monitorLocationMap,
|
||||
projectMonitorsCount,
|
||||
monitorQueryIdToConfigIdMap,
|
||||
} = processMonitors(this.monitors, this.server, this.soClient, this.syntheticsMonitorClient);
|
||||
} = processMonitors(this.monitors);
|
||||
|
||||
return {
|
||||
enabledMonitorQueryIds,
|
||||
|
|
|
@ -201,7 +201,7 @@ export async function queryMonitorStatus(
|
|||
configId: `${monitorQueryIdToConfigIdMap[queryId]}`,
|
||||
monitorQueryId: queryId,
|
||||
status: 'unknown',
|
||||
location: loc,
|
||||
locationId: loc,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,13 +34,7 @@ export const getSyntheticsCertsRoute: SyntheticsRestApiRouteFactory<
|
|||
to: schema.maybe(schema.string()),
|
||||
}),
|
||||
},
|
||||
handler: async ({
|
||||
request,
|
||||
syntheticsEsClient,
|
||||
savedObjectsClient,
|
||||
server,
|
||||
syntheticsMonitorClient,
|
||||
}) => {
|
||||
handler: async ({ request, syntheticsEsClient, savedObjectsClient }) => {
|
||||
const queryParams = request.query;
|
||||
|
||||
const monitors = await getAllMonitors({
|
||||
|
@ -57,12 +51,7 @@ export const getSyntheticsCertsRoute: SyntheticsRestApiRouteFactory<
|
|||
};
|
||||
}
|
||||
|
||||
const { enabledMonitorQueryIds } = processMonitors(
|
||||
monitors,
|
||||
server,
|
||||
savedObjectsClient,
|
||||
syntheticsMonitorClient
|
||||
);
|
||||
const { enabledMonitorQueryIds } = processMonitors(monitors);
|
||||
|
||||
const data = await getSyntheticsCerts({
|
||||
...queryParams,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
|
||||
import { FindActionResult } from '@kbn/actions-plugin/server';
|
||||
import { DynamicSettingsAttributes } from '../../runtime_types/settings';
|
||||
import { savedObjectsAdapter } from '../../saved_objects';
|
||||
import { populateAlertActions } from '../../../common/rules/alert_actions';
|
||||
import {
|
||||
|
@ -19,12 +20,12 @@ import {
|
|||
SYNTHETICS_STATUS_RULE,
|
||||
SYNTHETICS_TLS_RULE,
|
||||
} from '../../../common/constants/synthetics_alerts';
|
||||
|
||||
type DefaultRuleType = typeof SYNTHETICS_STATUS_RULE | typeof SYNTHETICS_TLS_RULE;
|
||||
import { DefaultRuleType } from '../../../common/types/default_alerts';
|
||||
export class DefaultAlertService {
|
||||
context: UptimeRequestHandlerContext;
|
||||
soClient: SavedObjectsClientContract;
|
||||
server: SyntheticsServerSetup;
|
||||
settings?: DynamicSettingsAttributes;
|
||||
|
||||
constructor(
|
||||
context: UptimeRequestHandlerContext,
|
||||
|
@ -36,7 +37,16 @@ export class DefaultAlertService {
|
|||
this.soClient = soClient;
|
||||
}
|
||||
|
||||
async getSettings() {
|
||||
if (!this.settings) {
|
||||
this.settings = await savedObjectsAdapter.getSyntheticsDynamicSettings(this.soClient);
|
||||
}
|
||||
return this.settings;
|
||||
}
|
||||
|
||||
async setupDefaultAlerts() {
|
||||
this.settings = await this.getSettings();
|
||||
|
||||
const [statusRule, tlsRule] = await Promise.allSettled([
|
||||
this.setupStatusRule(),
|
||||
this.setupTlsRule(),
|
||||
|
@ -50,12 +60,15 @@ export class DefaultAlertService {
|
|||
}
|
||||
|
||||
return {
|
||||
statusRule: statusRule.status === 'fulfilled' ? statusRule.value : null,
|
||||
tlsRule: tlsRule.status === 'fulfilled' ? tlsRule.value : null,
|
||||
statusRule: statusRule.status === 'fulfilled' && statusRule.value ? statusRule.value : null,
|
||||
tlsRule: tlsRule.status === 'fulfilled' && tlsRule.value ? tlsRule.value : null,
|
||||
};
|
||||
}
|
||||
|
||||
setupStatusRule() {
|
||||
if (this.settings?.defaultStatusRuleEnabled === false) {
|
||||
return;
|
||||
}
|
||||
return this.createDefaultAlertIfNotExist(
|
||||
SYNTHETICS_STATUS_RULE,
|
||||
`Synthetics status internal rule`,
|
||||
|
@ -64,6 +77,9 @@ export class DefaultAlertService {
|
|||
}
|
||||
|
||||
setupTlsRule() {
|
||||
if (this.settings?.defaultTLSRuleEnabled === false) {
|
||||
return;
|
||||
}
|
||||
return this.createDefaultAlertIfNotExist(
|
||||
SYNTHETICS_TLS_RULE,
|
||||
`Synthetics internal TLS rule`,
|
||||
|
@ -78,7 +94,7 @@ export class DefaultAlertService {
|
|||
options: {
|
||||
page: 1,
|
||||
perPage: 1,
|
||||
filter: `alert.attributes.alertTypeId:(${ruleType})`,
|
||||
filter: `alert.attributes.alertTypeId:(${ruleType}) AND alert.attributes.tags:"SYNTHETICS_DEFAULT_ALERT"`,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -88,6 +104,7 @@ export class DefaultAlertService {
|
|||
const { actions = [], systemActions = [], ...alert } = data[0];
|
||||
return { ...alert, actions: [...actions, ...systemActions], ruleTypeId: alert.alertTypeId };
|
||||
}
|
||||
|
||||
async createDefaultAlertIfNotExist(ruleType: DefaultRuleType, name: string, interval: string) {
|
||||
const alert = await this.getExistingAlert(ruleType);
|
||||
if (alert) {
|
||||
|
@ -121,11 +138,30 @@ export class DefaultAlertService {
|
|||
};
|
||||
}
|
||||
|
||||
updateStatusRule() {
|
||||
return this.updateDefaultAlert(SYNTHETICS_STATUS_RULE, `Synthetics status internal rule`, '1m');
|
||||
async updateStatusRule(enabled?: boolean) {
|
||||
if (enabled) {
|
||||
return this.updateDefaultAlert(
|
||||
SYNTHETICS_STATUS_RULE,
|
||||
`Synthetics status internal rule`,
|
||||
'1m'
|
||||
);
|
||||
} else {
|
||||
const rulesClient = (await this.context.alerting)?.getRulesClient();
|
||||
await rulesClient.bulkDeleteRules({
|
||||
filter: `alert.attributes.alertTypeId:"${SYNTHETICS_STATUS_RULE}" AND alert.attributes.tags:"SYNTHETICS_DEFAULT_ALERT"`,
|
||||
});
|
||||
}
|
||||
}
|
||||
updateTlsRule() {
|
||||
return this.updateDefaultAlert(SYNTHETICS_TLS_RULE, `Synthetics internal TLS rule`, '1m');
|
||||
|
||||
async updateTlsRule(enabled?: boolean) {
|
||||
if (enabled) {
|
||||
return this.updateDefaultAlert(SYNTHETICS_TLS_RULE, `Synthetics internal TLS rule`, '1m');
|
||||
} else {
|
||||
const rulesClient = (await this.context.alerting)?.getRulesClient();
|
||||
await rulesClient.bulkDeleteRules({
|
||||
filter: `alert.attributes.alertTypeId:"${SYNTHETICS_TLS_RULE}" AND alert.attributes.tags:"SYNTHETICS_DEFAULT_ALERT"`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async updateDefaultAlert(ruleType: DefaultRuleType, name: string, interval: string) {
|
||||
|
@ -195,14 +231,15 @@ export class DefaultAlertService {
|
|||
|
||||
async getActionConnectors() {
|
||||
const actionsClient = (await this.context.actions)?.getActionsClient();
|
||||
|
||||
const settings = await savedObjectsAdapter.getSyntheticsDynamicSettings(this.soClient);
|
||||
if (!this.settings) {
|
||||
this.settings = await savedObjectsAdapter.getSyntheticsDynamicSettings(this.soClient);
|
||||
}
|
||||
let actionConnectors: FindActionResult[] = [];
|
||||
try {
|
||||
actionConnectors = await actionsClient.getAll();
|
||||
} catch (e) {
|
||||
this.server.logger.error(e);
|
||||
}
|
||||
return { actionConnectors, settings };
|
||||
return { actionConnectors, settings: this.settings };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
import { DefaultAlertService } from './default_alert_service';
|
||||
import { SyntheticsRestApiRouteFactory } from '../types';
|
||||
import { SYNTHETICS_API_URLS } from '../../../common/constants';
|
||||
import { DEFAULT_ALERT_RESPONSE } from '../../../common/types/default_alerts';
|
||||
|
||||
export const enableDefaultAlertingRoute: SyntheticsRestApiRouteFactory = () => ({
|
||||
method: 'POST',
|
||||
path: SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING,
|
||||
validate: {},
|
||||
handler: async ({ context, server, savedObjectsClient }): Promise<any> => {
|
||||
handler: async ({ context, server, savedObjectsClient }): Promise<DEFAULT_ALERT_RESPONSE> => {
|
||||
const defaultAlertService = new DefaultAlertService(context, server, savedObjectsClient);
|
||||
|
||||
return defaultAlertService.setupDefaultAlerts();
|
||||
|
|
|
@ -12,19 +12,20 @@ import {
|
|||
import { DefaultAlertService } from './default_alert_service';
|
||||
import { SyntheticsRestApiRouteFactory } from '../types';
|
||||
import { SYNTHETICS_API_URLS } from '../../../common/constants';
|
||||
import { DEFAULT_ALERT_RESPONSE } from '../../../common/types/default_alerts';
|
||||
|
||||
export const getDefaultAlertingRoute: SyntheticsRestApiRouteFactory = () => ({
|
||||
method: 'GET',
|
||||
path: SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING,
|
||||
validate: {},
|
||||
handler: async ({ context, server, savedObjectsClient }): Promise<any> => {
|
||||
handler: async ({ context, server, savedObjectsClient }): Promise<DEFAULT_ALERT_RESPONSE> => {
|
||||
const defaultAlertService = new DefaultAlertService(context, server, savedObjectsClient);
|
||||
const statusRule = defaultAlertService.getExistingAlert(SYNTHETICS_STATUS_RULE);
|
||||
const tlsRule = defaultAlertService.getExistingAlert(SYNTHETICS_TLS_RULE);
|
||||
const [status, tls] = await Promise.all([statusRule, tlsRule]);
|
||||
return {
|
||||
statusRule: status,
|
||||
tlsRule: tls,
|
||||
statusRule: status || null,
|
||||
tlsRule: tls || null,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -8,21 +8,41 @@
|
|||
import { DefaultAlertService } from './default_alert_service';
|
||||
import { SyntheticsRestApiRouteFactory } from '../types';
|
||||
import { SYNTHETICS_API_URLS } from '../../../common/constants';
|
||||
import { savedObjectsAdapter } from '../../saved_objects';
|
||||
import { DEFAULT_ALERT_RESPONSE } from '../../../common/types/default_alerts';
|
||||
|
||||
export const updateDefaultAlertingRoute: SyntheticsRestApiRouteFactory = () => ({
|
||||
method: 'PUT',
|
||||
path: SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING,
|
||||
validate: {},
|
||||
handler: async ({ context, server, savedObjectsClient }): Promise<any> => {
|
||||
handler: async ({
|
||||
request,
|
||||
context,
|
||||
server,
|
||||
savedObjectsClient,
|
||||
}): Promise<DEFAULT_ALERT_RESPONSE> => {
|
||||
const defaultAlertService = new DefaultAlertService(context, server, savedObjectsClient);
|
||||
const { defaultTLSRuleEnabled, defaultStatusRuleEnabled } =
|
||||
await savedObjectsAdapter.getSyntheticsDynamicSettings(savedObjectsClient);
|
||||
|
||||
const [statusRule, tlsRule] = await Promise.all([
|
||||
defaultAlertService.updateStatusRule(),
|
||||
defaultAlertService.updateTlsRule(),
|
||||
]);
|
||||
return {
|
||||
statusRule,
|
||||
tlsRule,
|
||||
};
|
||||
const updateStatusRulePromise = defaultAlertService.updateStatusRule(defaultStatusRuleEnabled);
|
||||
const updateTLSRulePromise = defaultAlertService.updateTlsRule(defaultTLSRuleEnabled);
|
||||
|
||||
try {
|
||||
const [statusRule, tlsRule] = await Promise.all([
|
||||
updateStatusRulePromise,
|
||||
updateTLSRulePromise,
|
||||
]);
|
||||
return {
|
||||
statusRule: statusRule || null,
|
||||
tlsRule: tlsRule || null,
|
||||
};
|
||||
} catch (e) {
|
||||
server.logger.error(`Error updating default alerting rules: ${e}`);
|
||||
return {
|
||||
statusRule: null,
|
||||
tlsRule: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -593,25 +593,25 @@ describe('current status route', () => {
|
|||
pendingConfigs: {
|
||||
'id3-Asia/Pacific - Japan': {
|
||||
configId: 'id3',
|
||||
location: 'Asia/Pacific - Japan',
|
||||
locationId: 'Asia/Pacific - Japan',
|
||||
monitorQueryId: 'project-monitor-id',
|
||||
status: 'unknown',
|
||||
},
|
||||
'id3-Europe - Germany': {
|
||||
configId: 'id3',
|
||||
location: 'Europe - Germany',
|
||||
locationId: 'Europe - Germany',
|
||||
monitorQueryId: 'project-monitor-id',
|
||||
status: 'unknown',
|
||||
},
|
||||
'id4-Asia/Pacific - Japan': {
|
||||
configId: 'id4',
|
||||
location: 'Asia/Pacific - Japan',
|
||||
locationId: 'Asia/Pacific - Japan',
|
||||
monitorQueryId: 'id4',
|
||||
status: 'unknown',
|
||||
},
|
||||
'id4-Europe - Germany': {
|
||||
configId: 'id4',
|
||||
location: 'Europe - Germany',
|
||||
locationId: 'Europe - Germany',
|
||||
monitorQueryId: 'id4',
|
||||
status: 'unknown',
|
||||
},
|
||||
|
|
|
@ -36,7 +36,7 @@ export function periodToMs(schedule: { number: string; unit: Unit }) {
|
|||
* @returns The counts of up/down/disabled monitor by location, and a map of each monitor:location status.
|
||||
*/
|
||||
export async function getStatus(context: RouteContext, params: OverviewStatusQuery) {
|
||||
const { syntheticsEsClient, syntheticsMonitorClient, savedObjectsClient, server } = context;
|
||||
const { syntheticsEsClient, savedObjectsClient } = context;
|
||||
|
||||
const { query, scopeStatusByLocation = true } = params;
|
||||
|
||||
|
@ -77,13 +77,7 @@ export async function getStatus(context: RouteContext, params: OverviewStatusQue
|
|||
disabledMonitorsCount,
|
||||
projectMonitorsCount,
|
||||
monitorQueryIdToConfigIdMap,
|
||||
} = processMonitors(
|
||||
allMonitors,
|
||||
server,
|
||||
savedObjectsClient,
|
||||
syntheticsMonitorClient,
|
||||
queryLocations
|
||||
);
|
||||
} = processMonitors(allMonitors, queryLocations);
|
||||
|
||||
// Account for locations filter
|
||||
const listOfLocationAfterFilter =
|
||||
|
|
|
@ -22,7 +22,7 @@ export const createGetDynamicSettingsRoute: SyntheticsRestApiRouteFactory<
|
|||
handler: async ({ savedObjectsClient }) => {
|
||||
const dynamicSettingsAttributes: DynamicSettingsAttributes =
|
||||
await savedObjectsAdapter.getSyntheticsDynamicSettings(savedObjectsClient);
|
||||
return fromAttribute(dynamicSettingsAttributes);
|
||||
return fromSettingsAttribute(dynamicSettingsAttributes);
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -42,16 +42,20 @@ export const createPostDynamicSettingsRoute: SyntheticsRestApiRouteFactory = ()
|
|||
...newSettings,
|
||||
} as DynamicSettingsAttributes);
|
||||
|
||||
return fromAttribute(attr as DynamicSettingsAttributes);
|
||||
return fromSettingsAttribute(attr as DynamicSettingsAttributes);
|
||||
},
|
||||
});
|
||||
|
||||
const fromAttribute = (attr: DynamicSettingsAttributes) => {
|
||||
export const fromSettingsAttribute = (
|
||||
attr: DynamicSettingsAttributes
|
||||
): DynamicSettingsAttributes => {
|
||||
return {
|
||||
certExpirationThreshold: attr.certExpirationThreshold,
|
||||
certAgeThreshold: attr.certAgeThreshold,
|
||||
defaultConnectors: attr.defaultConnectors,
|
||||
defaultEmail: attr.defaultEmail,
|
||||
defaultStatusRuleEnabled: attr.defaultStatusRuleEnabled ?? true,
|
||||
defaultTLSRuleEnabled: attr.defaultTLSRuleEnabled ?? true,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -72,6 +76,8 @@ export const DynamicSettingsSchema = schema.object({
|
|||
certAgeThreshold: schema.maybe(schema.number({ min: 1, validate: validateInteger })),
|
||||
certExpirationThreshold: schema.maybe(schema.number({ min: 1, validate: validateInteger })),
|
||||
defaultConnectors: schema.maybe(schema.arrayOf(schema.string())),
|
||||
defaultStatusRuleEnabled: schema.maybe(schema.boolean()),
|
||||
defaultTLSRuleEnabled: schema.maybe(schema.boolean()),
|
||||
defaultEmail: schema.maybe(
|
||||
schema.object({
|
||||
to: schema.arrayOf(schema.string()),
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { SyntheticsRestApiRouteFactory } from '../types';
|
||||
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
|
||||
import { monitorAttributes, syntheticsMonitorType } from '../../../common/types/saved_objects';
|
||||
import {
|
||||
ConfigKey,
|
||||
MonitorFiltersResult,
|
||||
|
@ -30,7 +30,7 @@ interface AggsResponse {
|
|||
projectsAggs: {
|
||||
buckets: Buckets;
|
||||
};
|
||||
monitorTypeAggs: {
|
||||
monitorTypesAggs: {
|
||||
buckets: Buckets;
|
||||
};
|
||||
monitorIdsAggs: {
|
||||
|
@ -85,7 +85,7 @@ export const getSyntheticsSuggestionsRoute: SyntheticsRestApiRouteFactory<
|
|||
searchFields: SEARCH_FIELDS,
|
||||
});
|
||||
|
||||
const { monitorTypeAggs, tagsAggs, locationsAggs, projectsAggs, monitorIdsAggs } =
|
||||
const { monitorTypesAggs, tagsAggs, locationsAggs, projectsAggs, monitorIdsAggs } =
|
||||
(data?.aggregations as AggsResponse) ?? {};
|
||||
const allLocationsMap = new Map(allLocations.map((obj) => [obj.id, obj.label]));
|
||||
|
||||
|
@ -114,7 +114,7 @@ export const getSyntheticsSuggestionsRoute: SyntheticsRestApiRouteFactory<
|
|||
count,
|
||||
})) ?? [],
|
||||
monitorTypes:
|
||||
monitorTypeAggs?.buckets?.map(({ key, doc_count: count }) => ({
|
||||
monitorTypesAggs?.buckets?.map(({ key, doc_count: count }) => ({
|
||||
label: key,
|
||||
value: key,
|
||||
count,
|
||||
|
@ -129,35 +129,42 @@ export const getSyntheticsSuggestionsRoute: SyntheticsRestApiRouteFactory<
|
|||
const aggs = {
|
||||
tagsAggs: {
|
||||
terms: {
|
||||
field: `${syntheticsMonitorType}.attributes.${ConfigKey.TAGS}`,
|
||||
field: `${monitorAttributes}.${ConfigKey.TAGS}`,
|
||||
size: 10000,
|
||||
exclude: [''],
|
||||
},
|
||||
},
|
||||
monitorTypeAggs: {
|
||||
terms: {
|
||||
field: `${syntheticsMonitorType}.attributes.${ConfigKey.MONITOR_TYPE}.keyword`,
|
||||
field: `${monitorAttributes}.${ConfigKey.MONITOR_TYPE}.keyword`,
|
||||
size: 10000,
|
||||
exclude: [''],
|
||||
},
|
||||
},
|
||||
locationsAggs: {
|
||||
terms: {
|
||||
field: `${syntheticsMonitorType}.attributes.${ConfigKey.LOCATIONS}.id`,
|
||||
field: `${monitorAttributes}.${ConfigKey.LOCATIONS}.id`,
|
||||
size: 10000,
|
||||
exclude: [''],
|
||||
},
|
||||
},
|
||||
projectsAggs: {
|
||||
terms: {
|
||||
field: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}`,
|
||||
field: `${monitorAttributes}.${ConfigKey.PROJECT_ID}`,
|
||||
size: 10000,
|
||||
exclude: [''],
|
||||
},
|
||||
},
|
||||
monitorTypesAggs: {
|
||||
terms: {
|
||||
field: `${monitorAttributes}.${ConfigKey.MONITOR_TYPE}.keyword`,
|
||||
size: 10000,
|
||||
exclude: [''],
|
||||
},
|
||||
},
|
||||
monitorIdsAggs: {
|
||||
terms: {
|
||||
field: `${syntheticsMonitorType}.attributes.${ConfigKey.MONITOR_QUERY_ID}`,
|
||||
field: `${monitorAttributes}.${ConfigKey.MONITOR_QUERY_ID}`,
|
||||
size: 10000,
|
||||
exclude: [''],
|
||||
},
|
||||
|
|
|
@ -25,6 +25,8 @@ export const DynamicSettingsAttributesCodec = t.intersection([
|
|||
}),
|
||||
t.partial({
|
||||
defaultEmail: DefaultEmailCodec,
|
||||
defaultStatusRuleEnabled: t.boolean,
|
||||
defaultTLSRuleEnabled: t.boolean,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from '@kbn/core/server';
|
||||
import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server';
|
||||
|
||||
import { fromSettingsAttribute } from '../routes/settings/dynamic_settings';
|
||||
import {
|
||||
syntheticsSettings,
|
||||
syntheticsSettingsObjectId,
|
||||
|
@ -62,7 +63,7 @@ export const savedObjectsAdapter = {
|
|||
syntheticsSettingsObjectType,
|
||||
syntheticsSettingsObjectId
|
||||
);
|
||||
return obj?.attributes ?? DYNAMIC_SETTINGS_DEFAULT_ATTRIBUTES;
|
||||
return fromSettingsAttribute(obj?.attributes ?? DYNAMIC_SETTINGS_DEFAULT_ATTRIBUTES);
|
||||
} catch (getErr) {
|
||||
if (SavedObjectsErrorHelpers.isNotFoundError(getErr)) {
|
||||
// If the object doesn't exist, check to see if uptime settings exist
|
||||
|
|
|
@ -6,46 +6,11 @@
|
|||
*/
|
||||
|
||||
import { processMonitors } from './get_all_monitors';
|
||||
import { mockEncryptedSO } from '../../synthetics_service/utils/mocks';
|
||||
import { loggerMock } from '@kbn/logging-mocks';
|
||||
import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks';
|
||||
import { SyntheticsMonitorClient } from '../../synthetics_service/synthetics_monitor/synthetics_monitor_client';
|
||||
import { SyntheticsService } from '../../synthetics_service/synthetics_service';
|
||||
import * as getLocations from '../../synthetics_service/get_all_locations';
|
||||
import { SyntheticsServerSetup } from '../../types';
|
||||
|
||||
describe('processMonitors', () => {
|
||||
const mockEsClient = {
|
||||
search: jest.fn(),
|
||||
};
|
||||
const logger = loggerMock.create();
|
||||
const soClient = savedObjectsClientMock.create();
|
||||
|
||||
const serverMock: SyntheticsServerSetup = {
|
||||
logger,
|
||||
syntheticsEsClient: mockEsClient,
|
||||
authSavedObjectsClient: soClient,
|
||||
config: {
|
||||
service: {
|
||||
username: 'dev',
|
||||
password: '12345',
|
||||
manifestUrl: 'http://localhost:8080/api/manifest',
|
||||
},
|
||||
},
|
||||
spaces: {
|
||||
spacesService: {
|
||||
getSpaceId: jest.fn().mockReturnValue('test-space'),
|
||||
},
|
||||
},
|
||||
encryptedSavedObjects: mockEncryptedSO(),
|
||||
} as unknown as SyntheticsServerSetup;
|
||||
|
||||
const syntheticsService = new SyntheticsService(serverMock);
|
||||
|
||||
const monitorClient = new SyntheticsMonitorClient(syntheticsService, serverMock);
|
||||
|
||||
it('should return a processed data', async () => {
|
||||
const result = processMonitors(testMonitors, serverMock, soClient, monitorClient);
|
||||
const result = processMonitors(testMonitors);
|
||||
expect(result).toEqual({
|
||||
allIds: [
|
||||
'aa925d91-40b0-4f8f-b695-bb9b53cd4e22',
|
||||
|
@ -81,7 +46,7 @@ describe('processMonitors', () => {
|
|||
it('should return a processed data where location label is missing', async () => {
|
||||
testMonitors[0].attributes.locations[0].label = undefined;
|
||||
|
||||
const result = processMonitors(testMonitors, serverMock, soClient, monitorClient);
|
||||
const result = processMonitors(testMonitors);
|
||||
expect(result).toEqual({
|
||||
allIds: [
|
||||
'aa925d91-40b0-4f8f-b695-bb9b53cd4e22',
|
||||
|
@ -155,7 +120,7 @@ describe('processMonitors', () => {
|
|||
)
|
||||
);
|
||||
|
||||
const result = processMonitors(testMonitors, serverMock, soClient, monitorClient);
|
||||
const result = processMonitors(testMonitors);
|
||||
expect(result).toEqual({
|
||||
allIds: [
|
||||
'aa925d91-40b0-4f8f-b695-bb9b53cd4e22',
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
SavedObjectsFindResult,
|
||||
} from '@kbn/core-saved-objects-api-server';
|
||||
import { intersection } from 'lodash';
|
||||
import { SyntheticsServerSetup } from '../../types';
|
||||
import { syntheticsMonitorType } from '../../../common/types/saved_objects';
|
||||
import { periodToMs } from '../../routes/overview_status/overview_status';
|
||||
import {
|
||||
|
@ -19,7 +18,6 @@ import {
|
|||
EncryptedSyntheticsMonitorAttributes,
|
||||
SourceType,
|
||||
} from '../../../common/runtime_types';
|
||||
import { SyntheticsMonitorClient } from '../../synthetics_service/synthetics_monitor/synthetics_monitor_client';
|
||||
|
||||
export const getAllMonitors = async ({
|
||||
soClient,
|
||||
|
@ -57,9 +55,6 @@ export const getAllMonitors = async ({
|
|||
|
||||
export const processMonitors = (
|
||||
allMonitors: Array<SavedObjectsFindResult<EncryptedSyntheticsMonitorAttributes>>,
|
||||
server: SyntheticsServerSetup,
|
||||
soClient: SavedObjectsClientContract,
|
||||
syntheticsMonitorClient: SyntheticsMonitorClient,
|
||||
queryLocations?: string[] | string
|
||||
) => {
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
Logger,
|
||||
SavedObjectsClientContract,
|
||||
} from '@kbn/core/server';
|
||||
import { PluginStartContract as AlertingPluginStart } from '@kbn/alerting-plugin/server';
|
||||
import { SharePluginSetup } from '@kbn/share-plugin/server';
|
||||
import { ObservabilityPluginSetup } from '@kbn/observability-plugin/server';
|
||||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server';
|
||||
|
@ -85,6 +86,7 @@ export interface SyntheticsPluginsStartDependencies {
|
|||
taskManager: TaskManagerStartContract;
|
||||
telemetry: TelemetryPluginStart;
|
||||
spaces?: SpacesPluginStart;
|
||||
alerting: AlertingPluginStart;
|
||||
}
|
||||
|
||||
export type UptimeRequestHandlerContext = CustomRequestHandlerContext<{
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
"@kbn/react-kibana-context-render",
|
||||
"@kbn/react-kibana-context-theme",
|
||||
"@kbn/react-kibana-mount",
|
||||
"@kbn/deeplinks-observability"
|
||||
"@kbn/deeplinks-observability",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import expect from '@kbn/expect';
|
|||
import { omit } from 'lodash';
|
||||
import { HTTPFields } from '@kbn/synthetics-plugin/common/runtime_types';
|
||||
import { SYNTHETICS_API_URLS } from '@kbn/synthetics-plugin/common/constants';
|
||||
import { DYNAMIC_SETTINGS_DEFAULTS } from '@kbn/synthetics-plugin/common/constants/settings_defaults';
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { getFixtureJson } from './helper/get_fixture_json';
|
||||
|
@ -41,13 +42,19 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
beforeEach(async () => {
|
||||
httpMonitorJson = _httpMonitorJson;
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(DYNAMIC_SETTINGS_DEFAULTS)
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it('returns the created alerted when called', async () => {
|
||||
const apiResponse = await supertest
|
||||
.post(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({});
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const omitFields = [
|
||||
'id',
|
||||
|
@ -76,6 +83,96 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
expect(apiResponse).eql(omitMonitorKeys(newMonitor));
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
});
|
||||
|
||||
it('deletes (and recreates) the default rule when settings are updated', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse).eql(omitMonitorKeys(newMonitor));
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
const settings = await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
defaultStatusRuleEnabled: false,
|
||||
defaultTLSRuleEnabled: false,
|
||||
});
|
||||
|
||||
expect(settings.body.defaultStatusRuleEnabled).eql(false);
|
||||
expect(settings.body.defaultTLSRuleEnabled).eql(false);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule).eql(null);
|
||||
expect(res.body.tlsRule).eql(null);
|
||||
});
|
||||
|
||||
const settings2 = await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
defaultStatusRuleEnabled: true,
|
||||
defaultTLSRuleEnabled: true,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(settings2.body.defaultStatusRuleEnabled).eql(true);
|
||||
expect(settings2.body.defaultTLSRuleEnabled).eql(true);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
});
|
||||
|
||||
it('doesnt throw errors when rule has already been deleted', async () => {
|
||||
const newMonitor = httpMonitorJson;
|
||||
|
||||
const { body: apiResponse } = await addMonitorAPI(newMonitor);
|
||||
|
||||
expect(apiResponse).eql(omitMonitorKeys(newMonitor));
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
|
@ -84,6 +181,49 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
expect(res.body.statusRule.ruleTypeId).eql('xpack.synthetics.alerts.monitorStatus');
|
||||
expect(res.body.tlsRule.ruleTypeId).eql('xpack.synthetics.alerts.tls');
|
||||
});
|
||||
|
||||
const settings = await supertest
|
||||
.put(SYNTHETICS_API_URLS.DYNAMIC_SETTINGS)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
defaultStatusRuleEnabled: false,
|
||||
defaultTLSRuleEnabled: false,
|
||||
});
|
||||
|
||||
expect(settings.body.defaultStatusRuleEnabled).eql(false);
|
||||
expect(settings.body.defaultTLSRuleEnabled).eql(false);
|
||||
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send();
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule).eql(null);
|
||||
expect(res.body.tlsRule).eql(null);
|
||||
});
|
||||
|
||||
// call api again with the same settings, make sure its 200
|
||||
await supertest
|
||||
.put(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
await retry.tryForTime(30 * 1000, async () => {
|
||||
const res = await supertest
|
||||
.get(SYNTHETICS_API_URLS.ENABLE_DEFAULT_ALERTING)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.expect(200);
|
||||
|
||||
expect(res.body.statusRule).eql(null);
|
||||
expect(res.body.tlsRule).eql(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue