mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Contact Points v2 feature flag (#70165)
This commit is contained in:
parent
35d455e931
commit
69b1153205
@ -1,222 +1,24 @@
|
||||
import { css } from '@emotion/css';
|
||||
import pluralize from 'pluralize';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Redirect, Route, RouteChildrenProps, Switch, useLocation, useParams } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
import { Disable, Enable } from 'react-enable';
|
||||
|
||||
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
|
||||
import { Stack } from '@grafana/experimental';
|
||||
import { Alert, Icon, LoadingPlaceholder, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import { useDispatch } from 'app/types';
|
||||
import { withErrorBoundary } from '@grafana/ui';
|
||||
const ContactPointsV1 = SafeDynamicImport(() => import('./components/contact-points/ContactPoints.v1'));
|
||||
const ContactPointsV2 = SafeDynamicImport(() => import('./components/contact-points/ContactPoints.v2'));
|
||||
import { SafeDynamicImport } from 'app/core/components/DynamicImports/SafeDynamicImport';
|
||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||
|
||||
import { ContactPointsState } from '../../../types';
|
||||
|
||||
import { useGetContactPointsState } from './api/receiversApi';
|
||||
import { AlertManagerPicker } from './components/AlertManagerPicker';
|
||||
import { AlertingPageWrapper } from './components/AlertingPageWrapper';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from './components/GrafanaAlertmanagerDeliveryWarning';
|
||||
import { NoAlertManagerWarning } from './components/NoAlertManagerWarning';
|
||||
import { DuplicateTemplateView } from './components/receivers/DuplicateTemplateView';
|
||||
import { EditReceiverView } from './components/receivers/EditReceiverView';
|
||||
import { EditTemplateView } from './components/receivers/EditTemplateView';
|
||||
import { GlobalConfigForm } from './components/receivers/GlobalConfigForm';
|
||||
import { NewReceiverView } from './components/receivers/NewReceiverView';
|
||||
import { NewTemplateView } from './components/receivers/NewTemplateView';
|
||||
import { ReceiversAndTemplatesView } from './components/receivers/ReceiversAndTemplatesView';
|
||||
import { isDuplicating } from './components/receivers/TemplateForm';
|
||||
import { useAlertManagerSourceName } from './hooks/useAlertManagerSourceName';
|
||||
import { useAlertManagersByPermission } from './hooks/useAlertManagerSources';
|
||||
import { useUnifiedAlertingSelector } from './hooks/useUnifiedAlertingSelector';
|
||||
import { fetchAlertManagerConfigAction, fetchGrafanaNotifiersAction } from './state/actions';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
||||
import { initialAsyncRequestState } from './utils/redux';
|
||||
import { AlertingFeature } from './features';
|
||||
// TODO add pagenav back in – what are we missing if we don't specify it?
|
||||
const ContactPoints = (props: GrafanaRouteComponentProps): JSX.Element => (
|
||||
<AlertingPageWrapper pageId="receivers">
|
||||
<Enable feature={AlertingFeature.ContactPointsV2}>
|
||||
<ContactPointsV2 {...props} />
|
||||
</Enable>
|
||||
<Disable feature={AlertingFeature.ContactPointsV2}>
|
||||
<ContactPointsV1 {...props} />
|
||||
</Disable>
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
|
||||
export interface NotificationErrorProps {
|
||||
errorCount: number;
|
||||
}
|
||||
|
||||
function NotificationError({ errorCount }: NotificationErrorProps) {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<div className={styles.error} data-testid="receivers-notification-error">
|
||||
<Stack alignItems="flex-end" direction="column" gap={0}>
|
||||
<Stack alignItems="center" gap={1}>
|
||||
<Icon name="exclamation-circle" />
|
||||
<div>{`${errorCount} ${pluralize('error', errorCount)} with contact points`}</div>
|
||||
</Stack>
|
||||
<div>{'Some alert notifications might not be delivered'}</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type PageType = 'receivers' | 'templates' | 'global-config';
|
||||
|
||||
const Receivers = () => {
|
||||
const alertManagers = useAlertManagersByPermission('notification');
|
||||
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers);
|
||||
const dispatch = useDispatch();
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const { id, type } = useParams<{ id?: string; type?: PageType }>();
|
||||
const location = useLocation();
|
||||
const isRoot = location.pathname.endsWith('/alerting/notifications');
|
||||
const isduplicatingTemplate = isDuplicating(location);
|
||||
const configRequests = useUnifiedAlertingSelector((state) => state.amConfigs);
|
||||
|
||||
const {
|
||||
result: config,
|
||||
loading,
|
||||
error,
|
||||
} = (alertManagerSourceName && configRequests[alertManagerSourceName]) || initialAsyncRequestState;
|
||||
|
||||
const receiverTypes = useUnifiedAlertingSelector((state) => state.grafanaNotifiers);
|
||||
|
||||
const shouldLoadConfig = isRoot || !config;
|
||||
const shouldRenderNotificationStatus = isRoot;
|
||||
|
||||
useEffect(() => {
|
||||
if (alertManagerSourceName && shouldLoadConfig) {
|
||||
dispatch(fetchAlertManagerConfigAction(alertManagerSourceName));
|
||||
}
|
||||
}, [alertManagerSourceName, dispatch, shouldLoadConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME &&
|
||||
!(receiverTypes.result || receiverTypes.loading || receiverTypes.error)
|
||||
) {
|
||||
dispatch(fetchGrafanaNotifiersAction());
|
||||
}
|
||||
}, [alertManagerSourceName, dispatch, receiverTypes]);
|
||||
|
||||
const contactPointsState: ContactPointsState = useGetContactPointsState(alertManagerSourceName ?? '');
|
||||
const integrationsErrorCount = contactPointsState?.errorCount ?? 0;
|
||||
|
||||
const disableAmSelect = !isRoot;
|
||||
let pageNav = getPageNavigationModel(type, id ? decodeURIComponent(id) : undefined, isduplicatingTemplate);
|
||||
|
||||
if (!alertManagerSourceName) {
|
||||
return isRoot ? (
|
||||
<AlertingPageWrapper pageId="receivers" pageNav={pageNav}>
|
||||
<NoAlertManagerWarning availableAlertManagers={alertManagers} />
|
||||
</AlertingPageWrapper>
|
||||
) : (
|
||||
<Redirect to="/alerting/notifications" />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AlertingPageWrapper pageId="receivers" pageNav={pageNav}>
|
||||
<div className={styles.headingContainer}>
|
||||
<AlertManagerPicker
|
||||
current={alertManagerSourceName}
|
||||
disabled={disableAmSelect}
|
||||
onChange={setAlertManagerSourceName}
|
||||
dataSources={alertManagers}
|
||||
/>
|
||||
{shouldRenderNotificationStatus && integrationsErrorCount > 0 && (
|
||||
<NotificationError errorCount={integrationsErrorCount} />
|
||||
)}
|
||||
</div>
|
||||
{error && !loading && (
|
||||
<Alert severity="error" title="Error loading Alertmanager config">
|
||||
{error.message || 'Unknown error.'}
|
||||
</Alert>
|
||||
)}
|
||||
<GrafanaAlertmanagerDeliveryWarning currentAlertmanager={alertManagerSourceName} />
|
||||
{loading && !config && <LoadingPlaceholder text="loading configuration..." />}
|
||||
{config && !error && (
|
||||
<Switch>
|
||||
<Route exact={true} path="/alerting/notifications">
|
||||
<ReceiversAndTemplatesView config={config} alertManagerName={alertManagerSourceName} />
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/templates/new">
|
||||
<NewTemplateView config={config} alertManagerSourceName={alertManagerSourceName} />
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/templates/:name/duplicate">
|
||||
{({ match }: RouteChildrenProps<{ name: string }>) =>
|
||||
match?.params.name && (
|
||||
<DuplicateTemplateView
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
config={config}
|
||||
templateName={decodeURIComponent(match?.params.name)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/templates/:name/edit">
|
||||
{({ match }: RouteChildrenProps<{ name: string }>) =>
|
||||
match?.params.name && (
|
||||
<EditTemplateView
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
config={config}
|
||||
templateName={decodeURIComponent(match?.params.name)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/receivers/new">
|
||||
<NewReceiverView config={config} alertManagerSourceName={alertManagerSourceName} />
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/receivers/:name/edit">
|
||||
{({ match }: RouteChildrenProps<{ name: string }>) =>
|
||||
match?.params.name && (
|
||||
<EditReceiverView
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
config={config}
|
||||
receiverName={decodeURIComponent(match?.params.name)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/global-config">
|
||||
<GlobalConfigForm config={config} alertManagerSourceName={alertManagerSourceName} />
|
||||
</Route>
|
||||
</Switch>
|
||||
)}
|
||||
</AlertingPageWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
function getPageNavigationModel(type: PageType | undefined, id: string | undefined, isDuplicatingTemplates: boolean) {
|
||||
let pageNav: NavModelItem | undefined;
|
||||
if (isDuplicatingTemplates) {
|
||||
return {
|
||||
text: `New template`,
|
||||
subTitle: `Create a new template for your notifications`,
|
||||
};
|
||||
}
|
||||
if (type === 'receivers' || type === 'templates') {
|
||||
const objectText = type === 'receivers' ? 'contact point' : 'notification template';
|
||||
if (id) {
|
||||
pageNav = {
|
||||
text: id,
|
||||
subTitle: `Edit the settings for a specific ${objectText}`,
|
||||
};
|
||||
} else {
|
||||
pageNav = {
|
||||
text: `New ${objectText}`,
|
||||
subTitle: `Create a new ${objectText} for your notifications`,
|
||||
};
|
||||
}
|
||||
} else if (type === 'global-config') {
|
||||
pageNav = {
|
||||
text: 'Global config',
|
||||
subTitle: 'Manage your global configuration',
|
||||
};
|
||||
}
|
||||
return pageNav;
|
||||
}
|
||||
|
||||
export default withErrorBoundary(Receivers, { style: 'page' });
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
error: css`
|
||||
color: ${theme.colors.error.text};
|
||||
`,
|
||||
headingContainer: css`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`,
|
||||
});
|
||||
export default withErrorBoundary(ContactPoints, { style: 'page' });
|
||||
|
@ -20,30 +20,31 @@ import { AccessControlAction, ContactPointsState } from 'app/types';
|
||||
|
||||
import 'whatwg-fetch';
|
||||
|
||||
import Receivers from './Receivers';
|
||||
import { fetchAlertManagerConfig, fetchStatus, testReceivers, updateAlertManagerConfig } from './api/alertmanager';
|
||||
import { AlertmanagersChoiceResponse } from './api/alertmanagerApi';
|
||||
import { discoverAlertmanagerFeatures } from './api/buildInfo';
|
||||
import { fetchNotifiers } from './api/grafana';
|
||||
import * as receiversApi from './api/receiversApi';
|
||||
import * as grafanaApp from './components/receivers/grafanaAppReceivers/grafanaApp';
|
||||
import { fetchAlertManagerConfig, fetchStatus, testReceivers, updateAlertManagerConfig } from '../../api/alertmanager';
|
||||
import { AlertmanagersChoiceResponse } from '../../api/alertmanagerApi';
|
||||
import { discoverAlertmanagerFeatures } from '../../api/buildInfo';
|
||||
import { fetchNotifiers } from '../../api/grafana';
|
||||
import * as receiversApi from '../../api/receiversApi';
|
||||
import * as grafanaApp from '../../components/receivers/grafanaAppReceivers/grafanaApp';
|
||||
import {
|
||||
mockDataSource,
|
||||
MockDataSourceSrv,
|
||||
someCloudAlertManagerConfig,
|
||||
someCloudAlertManagerStatus,
|
||||
someGrafanaAlertManagerConfig,
|
||||
} from './mocks';
|
||||
import { mockAlertmanagerChoiceResponse } from './mocks/alertmanagerApi';
|
||||
import { grafanaNotifiersMock } from './mocks/grafana-notifiers';
|
||||
import { getAllDataSources } from './utils/config';
|
||||
import { ALERTMANAGER_NAME_LOCAL_STORAGE_KEY, ALERTMANAGER_NAME_QUERY_KEY } from './utils/constants';
|
||||
import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
||||
jest.mock('./api/alertmanager');
|
||||
jest.mock('./api/grafana');
|
||||
jest.mock('./utils/config');
|
||||
} from '../../mocks';
|
||||
import { mockAlertmanagerChoiceResponse } from '../../mocks/alertmanagerApi';
|
||||
import { grafanaNotifiersMock } from '../../mocks/grafana-notifiers';
|
||||
import { getAllDataSources } from '../../utils/config';
|
||||
import { ALERTMANAGER_NAME_LOCAL_STORAGE_KEY, ALERTMANAGER_NAME_QUERY_KEY } from '../../utils/constants';
|
||||
import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
|
||||
import Receivers from './ContactPoints.v1';
|
||||
jest.mock('../../api/alertmanager');
|
||||
jest.mock('../../api/grafana');
|
||||
jest.mock('../../utils/config');
|
||||
jest.mock('app/core/services/context_srv');
|
||||
jest.mock('./api/buildInfo');
|
||||
jest.mock('../../api/buildInfo');
|
||||
|
||||
const mocks = {
|
||||
getAllDataSources: jest.mocked(getAllDataSources),
|
@ -0,0 +1,181 @@
|
||||
import { css } from '@emotion/css';
|
||||
import pluralize from 'pluralize';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Stack } from '@grafana/experimental';
|
||||
import { Alert, Icon, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
|
||||
import { ContactPointsState, useDispatch } from 'app/types';
|
||||
|
||||
import { useGetContactPointsState } from '../../api/receiversApi';
|
||||
import { useAlertManagerSourceName } from '../../hooks/useAlertManagerSourceName';
|
||||
import { useAlertManagersByPermission } from '../../hooks/useAlertManagerSources';
|
||||
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
|
||||
import { fetchAlertManagerConfigAction, fetchGrafanaNotifiersAction } from '../../state/actions';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
|
||||
import { initialAsyncRequestState } from '../../utils/redux';
|
||||
import { AlertManagerPicker } from '../AlertManagerPicker';
|
||||
import { GrafanaAlertmanagerDeliveryWarning } from '../GrafanaAlertmanagerDeliveryWarning';
|
||||
import { NoAlertManagerWarning } from '../NoAlertManagerWarning';
|
||||
import { DuplicateTemplateView } from '../receivers/DuplicateTemplateView';
|
||||
import { EditReceiverView } from '../receivers/EditReceiverView';
|
||||
import { EditTemplateView } from '../receivers/EditTemplateView';
|
||||
import { GlobalConfigForm } from '../receivers/GlobalConfigForm';
|
||||
import { NewReceiverView } from '../receivers/NewReceiverView';
|
||||
import { NewTemplateView } from '../receivers/NewTemplateView';
|
||||
import { ReceiversAndTemplatesView } from '../receivers/ReceiversAndTemplatesView';
|
||||
|
||||
export interface NotificationErrorProps {
|
||||
errorCount: number;
|
||||
}
|
||||
|
||||
function NotificationError({ errorCount }: NotificationErrorProps) {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<div className={styles.error} data-testid="receivers-notification-error">
|
||||
<Stack alignItems="flex-end" direction="column" gap={0}>
|
||||
<Stack alignItems="center" gap={1}>
|
||||
<Icon name="exclamation-circle" />
|
||||
<div>{`${errorCount} ${pluralize('error', errorCount)} with contact points`}</div>
|
||||
</Stack>
|
||||
<div>{'Some alert notifications might not be delivered'}</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Receivers = () => {
|
||||
const alertManagers = useAlertManagersByPermission('notification');
|
||||
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers);
|
||||
const dispatch = useDispatch();
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const location = useLocation();
|
||||
const isRoot = location.pathname.endsWith('/alerting/notifications');
|
||||
const configRequests = useUnifiedAlertingSelector((state) => state.amConfigs);
|
||||
|
||||
const {
|
||||
result: config,
|
||||
loading,
|
||||
error,
|
||||
} = (alertManagerSourceName && configRequests[alertManagerSourceName]) || initialAsyncRequestState;
|
||||
|
||||
const receiverTypes = useUnifiedAlertingSelector((state) => state.grafanaNotifiers);
|
||||
|
||||
const shouldLoadConfig = isRoot || !config;
|
||||
const shouldRenderNotificationStatus = isRoot;
|
||||
|
||||
useEffect(() => {
|
||||
if (alertManagerSourceName && shouldLoadConfig) {
|
||||
dispatch(fetchAlertManagerConfigAction(alertManagerSourceName));
|
||||
}
|
||||
}, [alertManagerSourceName, dispatch, shouldLoadConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME &&
|
||||
!(receiverTypes.result || receiverTypes.loading || receiverTypes.error)
|
||||
) {
|
||||
dispatch(fetchGrafanaNotifiersAction());
|
||||
}
|
||||
}, [alertManagerSourceName, dispatch, receiverTypes]);
|
||||
|
||||
const contactPointsState: ContactPointsState = useGetContactPointsState(alertManagerSourceName ?? '');
|
||||
const integrationsErrorCount = contactPointsState?.errorCount ?? 0;
|
||||
|
||||
const disableAmSelect = !isRoot;
|
||||
|
||||
if (!alertManagerSourceName) {
|
||||
return isRoot ? (
|
||||
<NoAlertManagerWarning availableAlertManagers={alertManagers} />
|
||||
) : (
|
||||
<Redirect to="/alerting/notifications" />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.headingContainer}>
|
||||
<AlertManagerPicker
|
||||
current={alertManagerSourceName}
|
||||
disabled={disableAmSelect}
|
||||
onChange={setAlertManagerSourceName}
|
||||
dataSources={alertManagers}
|
||||
/>
|
||||
{shouldRenderNotificationStatus && integrationsErrorCount > 0 && (
|
||||
<NotificationError errorCount={integrationsErrorCount} />
|
||||
)}
|
||||
</div>
|
||||
{error && !loading && (
|
||||
<Alert severity="error" title="Error loading Alertmanager config">
|
||||
{error.message || 'Unknown error.'}
|
||||
</Alert>
|
||||
)}
|
||||
<GrafanaAlertmanagerDeliveryWarning currentAlertmanager={alertManagerSourceName} />
|
||||
{loading && !config && <LoadingPlaceholder text="loading configuration..." />}
|
||||
{config && !error && (
|
||||
<Switch>
|
||||
<Route exact={true} path="/alerting/notifications">
|
||||
<ReceiversAndTemplatesView config={config} alertManagerName={alertManagerSourceName} />
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/templates/new">
|
||||
<NewTemplateView config={config} alertManagerSourceName={alertManagerSourceName} />
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/templates/:name/duplicate">
|
||||
{({ match }: RouteChildrenProps<{ name: string }>) =>
|
||||
match?.params.name && (
|
||||
<DuplicateTemplateView
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
config={config}
|
||||
templateName={decodeURIComponent(match?.params.name)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/templates/:name/edit">
|
||||
{({ match }: RouteChildrenProps<{ name: string }>) =>
|
||||
match?.params.name && (
|
||||
<EditTemplateView
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
config={config}
|
||||
templateName={decodeURIComponent(match?.params.name)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/receivers/new">
|
||||
<NewReceiverView config={config} alertManagerSourceName={alertManagerSourceName} />
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/receivers/:name/edit">
|
||||
{({ match }: RouteChildrenProps<{ name: string }>) =>
|
||||
match?.params.name && (
|
||||
<EditReceiverView
|
||||
alertManagerSourceName={alertManagerSourceName}
|
||||
config={config}
|
||||
receiverName={decodeURIComponent(match?.params.name)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Route>
|
||||
<Route exact={true} path="/alerting/notifications/global-config">
|
||||
<GlobalConfigForm config={config} alertManagerSourceName={alertManagerSourceName} />
|
||||
</Route>
|
||||
</Switch>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Receivers;
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
error: css`
|
||||
color: ${theme.colors.error.text};
|
||||
`,
|
||||
headingContainer: css`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`,
|
||||
});
|
@ -0,0 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
const ContactPoints = () => <>Hello, contact points v2!</>;
|
||||
|
||||
export default ContactPoints;
|
@ -4,6 +4,7 @@ import { config } from '@grafana/runtime';
|
||||
|
||||
export enum AlertingFeature {
|
||||
NotificationPoliciesV2MatchingInstances = 'notification-policies.v2.matching-instances',
|
||||
ContactPointsV2 = 'contact-points.v2',
|
||||
}
|
||||
|
||||
const FEATURES: FeatureDescription[] = [
|
||||
@ -11,5 +12,9 @@ const FEATURES: FeatureDescription[] = [
|
||||
name: AlertingFeature.NotificationPoliciesV2MatchingInstances,
|
||||
defaultValue: config.featureToggles.alertingNotificationsPoliciesMatchingInstances,
|
||||
},
|
||||
{
|
||||
name: AlertingFeature.ContactPointsV2,
|
||||
defaultValue: false,
|
||||
},
|
||||
];
|
||||
export default FEATURES;
|
||||
|
Loading…
Reference in New Issue
Block a user