Alerting: Add notification policy provisioning file export (#70009)

* Alerting: Add notification policy provisioning file export

- Add provisioning API endpoint for exporting notification policies.
- Add option in notification policy view ellipsis dropdown for exporting.
- Update various provisioning documentation.
This commit is contained in:
Matthew Jacobson
2023-07-24 17:56:53 -04:00
committed by GitHub
parent 4c42632ab8
commit cfb1656968
16 changed files with 731 additions and 71 deletions

View File

@@ -13,11 +13,14 @@ import ConditionalWrap from 'app/features/alerting/components/ConditionalWrap';
import { RouteWithID, Receiver, ObjectMatcher, AlertmanagerGroup } from 'app/plugins/datasource/alertmanager/types';
import { ReceiversState } from 'app/types';
import { isOrgAdmin } from '../../../../plugins/admin/permissions';
import { INTEGRATION_ICONS } from '../../types/contact-points';
import { getNotificationsPermissions } from '../../utils/access-control';
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
import { normalizeMatchers } from '../../utils/matchers';
import { createContactPointLink, createMuteTimingLink } from '../../utils/misc';
import { getInheritedProperties, InhertitableProperties } from '../../utils/notification-policies';
import { createUrl } from '../../utils/url';
import { HoverCard } from '../HoverCard';
import { Label } from '../Label';
import { MetaText } from '../MetaText';
@@ -72,6 +75,7 @@ const Policy: FC<PolicyComponentProps> = ({
const permissions = getNotificationsPermissions(alertManagerSourceName);
const canEditRoutes = contextSrv.hasPermission(permissions.update);
const canDeleteRoutes = contextSrv.hasPermission(permissions.delete);
const canReadProvisioning = contextSrv.hasAccess(permissions.provisioning.read, isOrgAdmin());
const contactPoint = currentRoute.receiver;
const continueMatching = currentRoute.continue ?? false;
@@ -122,6 +126,9 @@ const Policy: FC<PolicyComponentProps> = ({
? sumBy(matchingAlertGroups, (group) => group.alerts.length)
: undefined;
const isGrafanaAM = alertManagerSourceName === GRAFANA_RULES_SOURCE_NAME;
const showExport = isGrafanaAM && isDefaultPolicy && canReadProvisioning;
// TODO dead branch detection, warnings for all sort of configs that won't work or will never be activated
return (
<Stack direction="column" gap={1.5}>
@@ -148,56 +155,73 @@ const Policy: FC<PolicyComponentProps> = ({
{/* TODO maybe we should move errors to the gutter instead? */}
{errors.length > 0 && <Errors errors={errors} />}
{provisioned && <ProvisioningBadge />}
{readOnly ? null : (
{readOnly && !showExport ? null : (
<Stack direction="row" gap={0.5}>
<ConditionalWrap shouldWrap={provisioned} wrap={ProvisionedTooltip}>
<Button
variant="secondary"
icon="plus"
size="sm"
onClick={() => onAddPolicy(currentRoute)}
disabled={provisioned}
type="button"
>
New nested policy
</Button>
</ConditionalWrap>
{!readOnly && (
<ConditionalWrap shouldWrap={provisioned} wrap={ProvisionedTooltip}>
<Button
variant="secondary"
icon="plus"
size="sm"
onClick={() => onAddPolicy(currentRoute)}
disabled={provisioned}
type="button"
>
New nested policy
</Button>
</ConditionalWrap>
)}
<ConditionalWrap shouldWrap={provisioned} wrap={ProvisionedTooltip}>
<Dropdown
overlay={
<Menu>
<Dropdown
overlay={
<Menu>
{!readOnly && (
<ConditionalWrap shouldWrap={provisioned} wrap={ProvisionedTooltip}>
<Menu.Item
icon="edit"
disabled={!isEditable || provisioned}
label="Edit"
onClick={() => onEditPolicy(currentRoute, isDefaultPolicy)}
/>
</ConditionalWrap>
)}
{showExport && (
<Menu.Item
icon="edit"
disabled={!isEditable}
label="Edit"
onClick={() => onEditPolicy(currentRoute, isDefaultPolicy)}
icon="download-alt"
label="Export"
url={createUrl('/api/v1/provisioning/policies/export', {
download: 'true',
format: 'yaml',
})}
target="_blank"
/>
{isDeletable && (
<>
<Menu.Divider />
)}
{!readOnly && isDeletable && (
<>
<Menu.Divider />
<ConditionalWrap shouldWrap={provisioned} wrap={ProvisionedTooltip}>
<Menu.Item
destructive
icon="trash-alt"
disabled={!isDeletable || provisioned}
label="Delete"
onClick={() => onDeletePolicy(currentRoute)}
/>
</>
)}
</Menu>
}
>
<Button
icon="ellipsis-h"
variant="secondary"
size="sm"
type="button"
aria-label="more-actions"
data-testid="more-actions"
disabled={provisioned}
/>
</Dropdown>
</ConditionalWrap>
</ConditionalWrap>
</>
)}
</Menu>
}
>
<Button
icon="ellipsis-h"
variant="secondary"
size="sm"
type="button"
aria-label="more-actions"
data-testid="more-actions"
/>
</Dropdown>
</Stack>
)}
</Stack>