Skip to content

Commit

Permalink
[Uptime] TLS alerting (elastic#63913)
Browse files Browse the repository at this point in the history
* Refactor settings form event handling and modify certs fields.

* Fix/improve broken types/unit/integration/api tests.

* Modify default expiration threshold.

* Rename test vars.

* Implement PR feedback.

* Refresh snapshots, fix broken tests/types.

* Remove unnecessary state spreading.

* Add type for settings field errors.

* Refresh test snapshots.

* Improve punctuation.

* Add TLS alert type.

* Add cert API request and runtime type checking.

* Add api test for cert api.

* Add unload command to certs test.

* Extract API params interface to io-ts type.

* Add TLS alert type on server.

* WIP - add state for changing selected alert type.

* Finish adding alert type for client, add server alert summary.

* Add some state variables.

* Update certs summary function to create required values.

* Refresh test snapshots.

* Clean up message generator function.

* Add a comment.

* Update formatting for alert messages, add flags denoting presence of age/expiration data.

* Add relative date information to tls alert messages.

* Clean up more logic in certs request function.

* Fix broken unit tests.

* Move tests for common function to new file.

* Fix logic error in test and add common state fields to tls alerts.

* Extract common state field translations from status check alert.

* Add a comment.

* Add nested context navigation for uptime alert selection.

* Clean up types.

* Fix translation key typo.

* Extract translations from tls alert factory.

* Extract summary messages to translation file.

* Change default tls alert time window from 1w to 1d.

* Remove unnecessary import.

* Simplify page linking.

* Extract a non-trivial component to a dedicated file.

* Simplify create alert copy.

* Fix broken functional test.

* Fix busted types.

* Fix tls query error.

* Allow for alerts toggle button to receive a set of types to display.

* Add alerts toggle button to certs page.

* Fix copy.

* Fixup punctuation in default message to avoid double-period symbols.

* Refresh snapshots.
  • Loading branch information
justinkambic committed May 5, 2020
1 parent e3de86b commit 21a7b74
Show file tree
Hide file tree
Showing 37 changed files with 1,260 additions and 409 deletions.
9 changes: 9 additions & 0 deletions x-pack/plugins/uptime/common/constants/alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,13 @@ export const ACTION_GROUP_DEFINITIONS: ActionGroupDefinitions = {
id: 'xpack.uptime.alerts.actionGroups.monitorStatus',
name: 'Uptime Down Monitor',
},
TLS: {
id: 'xpack.uptime.alerts.actionGroups.tls',
name: 'Uptime TLS Alert',
},
};

export const CLIENT_ALERT_TYPES = {
MONITOR_STATUS: 'xpack.uptime.alerts.monitorStatus',
TLS: 'xpack.uptime.alerts.tls',
};
2 changes: 1 addition & 1 deletion x-pack/plugins/uptime/common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

export { ACTION_GROUP_DEFINITIONS } from './alerts';
export * from './alerts';
export { CHART_FORMAT_LIMITS } from './chart_format_limits';
export { CLIENT_DEFAULTS } from './client_defaults';
export { CONTEXT_DEFAULTS } from './context_defaults';
Expand Down
23 changes: 23 additions & 0 deletions x-pack/plugins/uptime/common/runtime_types/alerts/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import * as t from 'io-ts';

export const UptimeCommonStateType = t.intersection([
t.partial({
currentTriggerStarted: t.string,
firstTriggeredAt: t.string,
lastTriggeredAt: t.string,
lastResolvedAt: t.string,
}),
t.type({
firstCheckedAt: t.string,
lastCheckedAt: t.string,
isTriggered: t.boolean,
}),
]);

export type UptimeCommonState = t.TypeOf<typeof UptimeCommonStateType>;
8 changes: 2 additions & 6 deletions x-pack/plugins/uptime/common/runtime_types/alerts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,5 @@
* you may not use this file except in compliance with the Elastic License.
*/

export {
StatusCheckAlertStateType,
StatusCheckAlertState,
StatusCheckExecutorParamsType,
StatusCheckExecutorParams,
} from './status_check';
export * from './common';
export * from './status_check';
16 changes: 0 additions & 16 deletions x-pack/plugins/uptime/common/runtime_types/alerts/status_check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,6 @@

import * as t from 'io-ts';

export const StatusCheckAlertStateType = t.intersection([
t.partial({
currentTriggerStarted: t.string,
firstTriggeredAt: t.string,
lastTriggeredAt: t.string,
lastResolvedAt: t.string,
}),
t.type({
firstCheckedAt: t.string,
lastCheckedAt: t.string,
isTriggered: t.boolean,
}),
]);

export type StatusCheckAlertState = t.TypeOf<typeof StatusCheckAlertStateType>;

export const StatusCheckExecutorParamsType = t.intersection([
t.partial({
filters: t.string,
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/uptime/common/runtime_types/certs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export const GetCertsParamsType = t.intersection([
}),
t.partial({
search: t.string,
notValidBefore: t.string,
notValidAfter: t.string,
from: t.string,
to: t.string,
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiExpression, EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui';
import React from 'react';
import { TlsTranslations } from './translations';
import { SettingsMessageExpressionPopover } from './settings_message_expression_popover';

interface Props {
ageThreshold?: number;
expirationThreshold?: number;
setAlertFlyoutVisible: (value: boolean) => void;
}

export const AlertTlsComponent: React.FC<Props> = props => (
<>
<EuiSpacer size="l" />
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem>
<EuiExpression
aria-label={TlsTranslations.criteriaAriaLabel}
color="secondary"
description={TlsTranslations.criteriaDescription}
value={TlsTranslations.criteriaValue}
/>
</EuiFlexItem>
<EuiFlexItem>
<SettingsMessageExpressionPopover
aria-label={TlsTranslations.expirationAriaLabel}
id="expiration"
description={TlsTranslations.expirationDescription}
value={TlsTranslations.expirationValue(props.expirationThreshold)}
{...props}
/>
</EuiFlexItem>
<EuiFlexItem>
<SettingsMessageExpressionPopover
aria-label={TlsTranslations.ageAriaLabel}
id="age"
description={TlsTranslations.ageDescription}
value={TlsTranslations.ageValue(props.ageThreshold)}
{...props}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="l" />
</>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { useDispatch, useSelector } from 'react-redux';
import React, { useCallback } from 'react';
import { AlertTlsComponent } from '../alert_tls';
import { setAlertFlyoutVisible } from '../../../../state/actions';
import { selectDynamicSettings } from '../../../../state/selectors';

export const AlertTls = () => {
const dispatch = useDispatch();
const setFlyoutVisible = useCallback((value: boolean) => dispatch(setAlertFlyoutVisible(value)), [
dispatch,
]);
const { settings } = useSelector(selectDynamicSettings);
return (
<AlertTlsComponent
ageThreshold={settings?.certThresholds?.age}
expirationThreshold={settings?.certThresholds?.expiration}
setAlertFlyoutVisible={setFlyoutVisible}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
*/

export { AlertMonitorStatus } from './alert_monitor_status';
export { ToggleAlertFlyoutButton } from './toggle_alert_flyout_button';
export {
ToggleAlertFlyoutButton,
ToggleAlertFlyoutButtonProps,
} from './toggle_alert_flyout_button';
export { UptimeAlertsFlyoutWrapper } from './uptime_alerts_flyout_wrapper';
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,26 @@

import React from 'react';
import { useDispatch } from 'react-redux';
import { setAlertFlyoutVisible } from '../../../../state/actions';
import { setAlertFlyoutType, setAlertFlyoutVisible } from '../../../../state/actions';
import { ToggleAlertFlyoutButtonComponent } from '../index';

export const ToggleAlertFlyoutButton = () => {
export interface ToggleAlertFlyoutButtonProps {
alertOptions?: string[];
}

export const ToggleAlertFlyoutButton: React.FC<ToggleAlertFlyoutButtonProps> = props => {
const dispatch = useDispatch();
return (
<ToggleAlertFlyoutButtonComponent
setAlertFlyoutVisible={(value: boolean) => dispatch(setAlertFlyoutVisible(value))}
{...props}
setAlertFlyoutVisible={(value: boolean | string) => {
if (typeof value === 'string') {
dispatch(setAlertFlyoutType(value));
dispatch(setAlertFlyoutVisible(true));
} else {
dispatch(setAlertFlyoutVisible(value));
}
}}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,22 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { setAlertFlyoutVisible } from '../../../../state/actions';
import { selectAlertFlyoutVisibility } from '../../../../state/selectors';
import { UptimeAlertsFlyoutWrapperComponent } from '../index';
import { UptimeAlertsFlyoutWrapperComponent } from '../uptime_alerts_flyout_wrapper';
import { selectAlertFlyoutVisibility, selectAlertFlyoutType } from '../../../../state/selectors';

interface Props {
alertTypeId?: string;
canChangeTrigger?: boolean;
}

export const UptimeAlertsFlyoutWrapper = ({ alertTypeId, canChangeTrigger }: Props) => {
export const UptimeAlertsFlyoutWrapper: React.FC = () => {
const dispatch = useDispatch();
const setAddFlyoutVisibility = (value: React.SetStateAction<boolean>) =>
// @ts-ignore the value here is a boolean, and it works with the action creator function
dispatch(setAlertFlyoutVisible(value));

const alertFlyoutVisible = useSelector(selectAlertFlyoutVisibility);
const alertTypeId = useSelector(selectAlertFlyoutType);

return (
<UptimeAlertsFlyoutWrapperComponent
alertFlyoutVisible={alertFlyoutVisible}
alertTypeId={alertTypeId}
canChangeTrigger={canChangeTrigger}
setAlertFlyoutVisibility={setAddFlyoutVisibility}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiExpression, EuiPopover } from '@elastic/eui';
import { Link } from 'react-router-dom';
import React, { useState } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { SETTINGS_ROUTE } from '../../../../common/constants';

interface SettingsMessageExpressionPopoverProps {
'aria-label': string;
description: string;
id: string;
setAlertFlyoutVisible: (value: boolean) => void;
value: string;
}

export const SettingsMessageExpressionPopover: React.FC<SettingsMessageExpressionPopoverProps> = ({
'aria-label': ariaLabel,
description,
setAlertFlyoutVisible,
value,
id,
}) => {
const [isOpen, setIsOpen] = useState(false);
return (
<EuiPopover
id={id}
anchorPosition="downLeft"
button={
<EuiExpression
aria-label={ariaLabel}
color="secondary"
description={description}
isActive={isOpen}
onClick={() => setIsOpen(!isOpen)}
value={value}
/>
}
isOpen={isOpen}
closePopover={() => setIsOpen(false)}
>
<FormattedMessage
id="xpack.uptime.alerts.tls.settingsPageNav.text"
defaultMessage="You can edit these thresholds on the {settingsPageLink}."
values={{
settingsPageLink: (
// this link is wrapped around a span so we can also change the UI state
// and hide the alert flyout before triggering the navigation to the settings page
<Link to={SETTINGS_ROUTE} data-test-subj="xpack.uptime.alerts.tlsFlyout.linkToSettings">
<span
onClick={() => {
setAlertFlyoutVisible(false);
}}
onKeyUp={e => {
if (e.key === 'Enter') {
setAlertFlyoutVisible(false);
}
}}
>
settings page
</span>
</Link>
),
}}
/>
</EuiPopover>
);
};
Loading

0 comments on commit 21a7b74

Please sign in to comment.