@grafana/alerting
Version:
Grafana Alerting Library – Build vertical integrations on top of the industry-leading alerting solution
1,169 lines (1,150 loc) • 40.6 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var jsxRuntime = require('react/jsx-runtime');
var css = require('@emotion/css');
var lodash = require('lodash');
var react = require('react');
var i18n = require('@grafana/i18n');
var ui = require('@grafana/ui');
var tinycolor2 = require('tinycolor2');
var react$1 = require('@reduxjs/toolkit/query/react');
var runtime = require('@grafana/runtime');
var data = require('@grafana/data');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
var tinycolor2__default = /*#__PURE__*/_interopDefaultCompat(tinycolor2);
;
const GRAFANA_ORIGIN_LABEL = "__grafana_origin";
function isPrivateLabelKey(labelKey) {
return labelKey.startsWith("__") && labelKey.endsWith("__") || labelKey === GRAFANA_ORIGIN_LABEL;
}
const isPrivateLabel = ([key, _]) => isPrivateLabelKey(key);
function findCommonLabels(labelSets) {
if (!Array.isArray(labelSets) || labelSets.length === 0) {
return {};
}
return labelSets.reduce(
(acc, labels) => {
if (!labels) {
throw new Error("Need parsed labels to find common labels.");
}
Object.keys(labels).forEach((key) => {
if (acc[key] === void 0 || acc[key] !== labels[key]) {
delete acc[key];
}
});
Object.keys(acc).forEach((key) => {
if (labels[key] === void 0) {
delete acc[key];
}
});
return acc;
},
{ ...labelSets[0] }
);
}
;
const AlertLabel = (props) => {
const { labelKey, value, icon, color, colorBy, size = "md", onClick, ...rest } = props;
const theColor = getColorFromProps({ color, colorBy, labelKey, value });
const styles = ui.useStyles2(getStyles$1, theColor, size);
const ariaLabel = `${labelKey}: ${value}`;
const keyless = !Boolean(labelKey);
const innerLabel = react.useMemo(
() => /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { direction: "row", gap: 0, alignItems: "stretch", children: [
labelKey && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.label, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { direction: "row", gap: 0.5, alignItems: "center", children: [
icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: icon }),
labelKey && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.labelText, title: labelKey.toString(), children: labelKey != null ? labelKey : "" })
] }) }),
/* @__PURE__ */ jsxRuntime.jsx("div", { className: css.cx(styles.value, keyless && styles.valueWithoutKey), title: value == null ? void 0 : value.toString(), children: value != null ? value : "-" })
] }),
[labelKey, styles.label, styles.labelText, styles.value, styles.valueWithoutKey, icon, keyless, value]
);
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.wrapper, "aria-label": ariaLabel, "data-testid": "label-value", ...rest, children: onClick && (labelKey || value) ? /* @__PURE__ */ jsxRuntime.jsx(
"button",
{
type: "button",
className: styles.clickable,
onClick: () => onClick == null ? void 0 : onClick([value != null ? value : "", labelKey != null ? labelKey : ""]),
children: innerLabel
},
`${labelKey != null ? labelKey : ""}${value != null ? value : ""}`
) : innerLabel });
};
function getAccessibleTagColor(name) {
if (!name) {
return;
}
const attempts = Array.from({ length: 6 }, (_, i) => name + "-".repeat(i));
const readableAttempt = attempts.find((attempt) => {
const candidate = ui.getTagColorsFromName(attempt).color;
return tinycolor2__default.default.isReadable(candidate, "#000", { level: "AA", size: "small" }) || tinycolor2__default.default.isReadable(candidate, "#fff", { level: "AA", size: "small" });
});
const chosen = readableAttempt != null ? readableAttempt : name;
return ui.getTagColorsFromName(chosen).color;
}
function getColorFromProps({
color,
colorBy,
labelKey,
value
}) {
if (color) {
return getAccessibleTagColor(color);
}
if (colorBy === "key") {
return getAccessibleTagColor(labelKey);
}
if (colorBy === "value") {
return getAccessibleTagColor(value);
}
if (colorBy === "both" && labelKey && value) {
return getAccessibleTagColor(labelKey + value);
}
return;
}
function getReadableFontColor(bg, fallback) {
if (tinycolor2__default.default.isReadable(bg, "#000", { level: "AA", size: "small" })) {
return "#000";
}
if (tinycolor2__default.default.isReadable(bg, "#fff", { level: "AA", size: "small" })) {
return "#fff";
}
if (tinycolor2__default.default.isReadable(bg, fallback, { level: "AA", size: "small" })) {
return tinycolor2__default.default(fallback).toHexString();
}
return tinycolor2__default.default.mostReadable(bg, ["#000", "#fff", fallback], {
includeFallbackColors: true
}).toHexString();
}
const getStyles$1 = (theme, color, size) => {
const backgroundColor = color != null ? color : theme.colors.secondary.main;
const borderColor = theme.isDark ? tinycolor2__default.default(backgroundColor).lighten(5).toString() : tinycolor2__default.default(backgroundColor).darken(5).toString();
const valueBackgroundColor = theme.isDark ? tinycolor2__default.default(backgroundColor).darken(5).toString() : tinycolor2__default.default(backgroundColor).lighten(5).toString();
const labelFontColor = color ? getReadableFontColor(backgroundColor, theme.colors.text.primary) : theme.colors.text.primary;
const valueFontColor = color ? getReadableFontColor(valueBackgroundColor, theme.colors.text.primary) : theme.colors.text.primary;
let padding = theme.spacing(0.33, 1);
switch (size) {
case "sm":
padding = theme.spacing(0.2, 0.6);
break;
case "xs":
padding = theme.spacing(0, 0.5);
break;
default:
break;
}
return {
wrapper: css.css({
fontSize: theme.typography.bodySmall.fontSize,
borderRadius: theme.shape.borderRadius(2)
}),
labelText: css.css({
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
maxWidth: "300px"
}),
label: css.css({
display: "flex",
alignItems: "center",
color: labelFontColor,
padding,
background: backgroundColor,
border: `solid 1px ${borderColor}`,
borderTopLeftRadius: theme.shape.borderRadius(2),
borderBottomLeftRadius: theme.shape.borderRadius(2)
}),
clickable: css.css({
border: "none",
background: "none",
outline: "none",
boxShadow: "none",
padding: 0,
margin: 0,
"&:hover": {
opacity: 0.8,
cursor: "pointer"
}
}),
value: css.css({
color: valueFontColor,
padding,
background: valueBackgroundColor,
border: `solid 1px ${borderColor}`,
borderLeft: "none",
borderTopRightRadius: theme.shape.borderRadius(2),
borderBottomRightRadius: theme.shape.borderRadius(2),
whiteSpace: "pre",
overflow: "hidden",
textOverflow: "ellipsis",
maxWidth: "300px"
}),
valueWithoutKey: css.css({
borderTopLeftRadius: theme.shape.borderRadius(2),
borderBottomLeftRadius: theme.shape.borderRadius(2),
borderLeft: `solid 1px ${borderColor}`
})
};
};
;
const AlertLabels = ({
labels,
displayCommonLabels,
labelSets,
size,
onClick,
commonLabelsMode = "expand"
}) => {
const styles = ui.useStyles2(getStyles, size);
const [showCommonLabels, setShowCommonLabels] = react.useState(false);
const computedCommonLabels = react.useMemo(
() => displayCommonLabels && Array.isArray(labelSets) && labelSets.length > 1 ? findCommonLabels(labelSets) : {},
[displayCommonLabels, labelSets]
);
const labelsToShow = lodash.chain(labels).toPairs().reject(isPrivateLabel).reject(([key]) => showCommonLabels ? false : key in computedCommonLabels).value();
const commonLabelsCount = Object.keys(computedCommonLabels).length;
const hasCommonLabels = commonLabelsCount > 0;
const tooltip = i18n.t("alert-labels.button.show.tooltip", "Show common labels");
const commonLabelsTooltip = react.useMemo(
() => /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { "data-testid": "common-labels-tooltip-content", role: "list", direction: "row", wrap: "wrap", gap: 1, width: 48, children: Object.entries(computedCommonLabels).map(([label, value]) => /* @__PURE__ */ jsxRuntime.jsx(AlertLabel, { size, labelKey: label, value, colorBy: "key", role: "listitem" }, label + value)) }),
[computedCommonLabels, size]
);
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.wrapper, role: "list", "aria-label": i18n.t("alerting.alert-labels.aria-label-labels", "Labels"), children: [
labelsToShow.map(([label, value]) => {
return /* @__PURE__ */ jsxRuntime.jsx(
AlertLabel,
{
size,
labelKey: label,
value,
colorBy: "key",
onClick,
role: "listitem"
},
label + value
);
}),
!showCommonLabels && hasCommonLabels && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listitem", children: commonLabelsMode === "expand" ? /* @__PURE__ */ jsxRuntime.jsx(
ui.Button,
{
variant: "secondary",
fill: "text",
onClick: () => setShowCommonLabels(true),
tooltip,
tooltipPlacement: "top",
size: "sm",
children: /* @__PURE__ */ jsxRuntime.jsxs(i18n.Trans, { i18nKey: "alerting.alert-labels.common-labels-count", count: commonLabelsCount, children: [
"+",
"{{count}}",
" common labels"
] })
}
) : /* @__PURE__ */ jsxRuntime.jsx(ui.Toggletip, { content: commonLabelsTooltip, closeButton: false, fitContent: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { "data-testid": "common-labels-tooltip-trigger", variant: "secondary", fill: "text", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs(i18n.Trans, { i18nKey: "alerting.alert-labels.common-labels-count", count: commonLabelsCount, children: [
"+",
"{{count}}",
" common labels"
] }) }) }) }),
showCommonLabels && hasCommonLabels && /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listitem", children: /* @__PURE__ */ jsxRuntime.jsx(
ui.Button,
{
variant: "secondary",
fill: "text",
onClick: () => setShowCommonLabels(false),
tooltipPlacement: "top",
size: "sm",
children: /* @__PURE__ */ jsxRuntime.jsx(i18n.Trans, { i18nKey: "alert-labels.button.hide", children: "Hide common labels" })
}
) })
] });
};
const getStyles = (theme, size) => {
return {
wrapper: css.css({
display: "flex",
flexWrap: "wrap",
alignItems: "center",
gap: size === "md" ? theme.spacing() : theme.spacing(0.5)
})
};
};
;
const getAPINamespace = () => runtime.config.namespace;
const getAPIBaseURL = (group, version) => {
const subPath = runtime.config.appSubUrl || "";
return `${subPath}/apis/${group}/${version}/namespaces/${getAPINamespace()}`;
};
const getAPIReducerPath = (group, version) => `${group}/${version}`;
const isWellFormed = (str) => {
try {
encodeURIComponent(str);
return true;
} catch (error) {
return false;
}
};
const base64UrlEncode = (value) => {
if (!isWellFormed(value)) {
throw new Error(`Cannot encode malformed UTF-16 string with lone surrogates: ${value}`);
}
const bytes = new TextEncoder().encode(value);
const binString = String.fromCodePoint(...bytes);
const base64 = btoa(binString);
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
};
;
const VERSION = "v0alpha1";
const GROUP = "notifications.alerting.grafana.app";
;
const baseUrl = getAPIBaseURL(GROUP, VERSION);
const reducerPath = getAPIReducerPath(GROUP, VERSION);
const api = react$1.createApi({
reducerPath,
baseQuery: react$1.fetchBaseQuery({
// Set URL correctly so MSW can intercept requests
// https://mswjs.io/docs/runbook#rtk-query-requests-are-not-intercepted
baseUrl: new URL(baseUrl, globalThis.location.origin).href
}),
endpoints: () => ({})
});
;
const addTagTypes = ["API Discovery", "Receiver", "RoutingTree", "TemplateGroup", "TimeInterval"];
const injectedRtkApi = api.enhanceEndpoints({
addTagTypes
}).injectEndpoints({
endpoints: (build) => ({
getApiResources: build.query({
query: () => ({ url: `/apis/notifications.alerting.grafana.app/v0alpha1/` }),
providesTags: ["API Discovery"]
}),
listReceiver: build.query({
query: (queryArg) => ({
url: `/receivers`,
params: {
pretty: queryArg.pretty,
allowWatchBookmarks: queryArg.allowWatchBookmarks,
continue: queryArg["continue"],
fieldSelector: queryArg.fieldSelector,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds,
watch: queryArg.watch
}
}),
providesTags: ["Receiver"]
}),
createReceiver: build.mutation({
query: (queryArg) => ({
url: `/receivers`,
method: "POST",
body: queryArg.receiver,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["Receiver"]
}),
deletecollectionReceiver: build.mutation({
query: (queryArg) => ({
url: `/receivers`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
continue: queryArg["continue"],
dryRun: queryArg.dryRun,
fieldSelector: queryArg.fieldSelector,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds
}
}),
invalidatesTags: ["Receiver"]
}),
getReceiver: build.query({
query: (queryArg) => ({
url: `/receivers/${queryArg.name}`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["Receiver"]
}),
replaceReceiver: build.mutation({
query: (queryArg) => ({
url: `/receivers/${queryArg.name}`,
method: "PUT",
body: queryArg.receiver,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["Receiver"]
}),
deleteReceiver: build.mutation({
query: (queryArg) => ({
url: `/receivers/${queryArg.name}`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy
}
}),
invalidatesTags: ["Receiver"]
}),
updateReceiver: build.mutation({
query: (queryArg) => ({
url: `/receivers/${queryArg.name}`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["Receiver"]
}),
getReceiverStatus: build.query({
query: (queryArg) => ({
url: `/receivers/${queryArg.name}/status`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["Receiver"]
}),
replaceReceiverStatus: build.mutation({
query: (queryArg) => ({
url: `/receivers/${queryArg.name}/status`,
method: "PUT",
body: queryArg.receiver,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["Receiver"]
}),
updateReceiverStatus: build.mutation({
query: (queryArg) => ({
url: `/receivers/${queryArg.name}/status`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["Receiver"]
}),
listRoutingTree: build.query({
query: (queryArg) => ({
url: `/routingtrees`,
params: {
pretty: queryArg.pretty,
allowWatchBookmarks: queryArg.allowWatchBookmarks,
continue: queryArg["continue"],
fieldSelector: queryArg.fieldSelector,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds,
watch: queryArg.watch
}
}),
providesTags: ["RoutingTree"]
}),
createRoutingTree: build.mutation({
query: (queryArg) => ({
url: `/routingtrees`,
method: "POST",
body: queryArg.routingTree,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["RoutingTree"]
}),
deletecollectionRoutingTree: build.mutation({
query: (queryArg) => ({
url: `/routingtrees`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
continue: queryArg["continue"],
dryRun: queryArg.dryRun,
fieldSelector: queryArg.fieldSelector,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds
}
}),
invalidatesTags: ["RoutingTree"]
}),
getRoutingTree: build.query({
query: (queryArg) => ({
url: `/routingtrees/${queryArg.name}`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["RoutingTree"]
}),
replaceRoutingTree: build.mutation({
query: (queryArg) => ({
url: `/routingtrees/${queryArg.name}`,
method: "PUT",
body: queryArg.routingTree,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["RoutingTree"]
}),
deleteRoutingTree: build.mutation({
query: (queryArg) => ({
url: `/routingtrees/${queryArg.name}`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy
}
}),
invalidatesTags: ["RoutingTree"]
}),
updateRoutingTree: build.mutation({
query: (queryArg) => ({
url: `/routingtrees/${queryArg.name}`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["RoutingTree"]
}),
getRoutingTreeStatus: build.query({
query: (queryArg) => ({
url: `/routingtrees/${queryArg.name}/status`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["RoutingTree"]
}),
replaceRoutingTreeStatus: build.mutation({
query: (queryArg) => ({
url: `/routingtrees/${queryArg.name}/status`,
method: "PUT",
body: queryArg.routingTree,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["RoutingTree"]
}),
updateRoutingTreeStatus: build.mutation({
query: (queryArg) => ({
url: `/routingtrees/${queryArg.name}/status`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["RoutingTree"]
}),
listTemplateGroup: build.query({
query: (queryArg) => ({
url: `/templategroups`,
params: {
pretty: queryArg.pretty,
allowWatchBookmarks: queryArg.allowWatchBookmarks,
continue: queryArg["continue"],
fieldSelector: queryArg.fieldSelector,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds,
watch: queryArg.watch
}
}),
providesTags: ["TemplateGroup"]
}),
createTemplateGroup: build.mutation({
query: (queryArg) => ({
url: `/templategroups`,
method: "POST",
body: queryArg.templateGroup,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["TemplateGroup"]
}),
deletecollectionTemplateGroup: build.mutation({
query: (queryArg) => ({
url: `/templategroups`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
continue: queryArg["continue"],
dryRun: queryArg.dryRun,
fieldSelector: queryArg.fieldSelector,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds
}
}),
invalidatesTags: ["TemplateGroup"]
}),
getTemplateGroup: build.query({
query: (queryArg) => ({
url: `/templategroups/${queryArg.name}`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["TemplateGroup"]
}),
replaceTemplateGroup: build.mutation({
query: (queryArg) => ({
url: `/templategroups/${queryArg.name}`,
method: "PUT",
body: queryArg.templateGroup,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["TemplateGroup"]
}),
deleteTemplateGroup: build.mutation({
query: (queryArg) => ({
url: `/templategroups/${queryArg.name}`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy
}
}),
invalidatesTags: ["TemplateGroup"]
}),
updateTemplateGroup: build.mutation({
query: (queryArg) => ({
url: `/templategroups/${queryArg.name}`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["TemplateGroup"]
}),
getTemplateGroupStatus: build.query({
query: (queryArg) => ({
url: `/templategroups/${queryArg.name}/status`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["TemplateGroup"]
}),
replaceTemplateGroupStatus: build.mutation({
query: (queryArg) => ({
url: `/templategroups/${queryArg.name}/status`,
method: "PUT",
body: queryArg.templateGroup,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["TemplateGroup"]
}),
updateTemplateGroupStatus: build.mutation({
query: (queryArg) => ({
url: `/templategroups/${queryArg.name}/status`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["TemplateGroup"]
}),
listTimeInterval: build.query({
query: (queryArg) => ({
url: `/timeintervals`,
params: {
pretty: queryArg.pretty,
allowWatchBookmarks: queryArg.allowWatchBookmarks,
continue: queryArg["continue"],
fieldSelector: queryArg.fieldSelector,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds,
watch: queryArg.watch
}
}),
providesTags: ["TimeInterval"]
}),
createTimeInterval: build.mutation({
query: (queryArg) => ({
url: `/timeintervals`,
method: "POST",
body: queryArg.timeInterval,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["TimeInterval"]
}),
deletecollectionTimeInterval: build.mutation({
query: (queryArg) => ({
url: `/timeintervals`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
continue: queryArg["continue"],
dryRun: queryArg.dryRun,
fieldSelector: queryArg.fieldSelector,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
labelSelector: queryArg.labelSelector,
limit: queryArg.limit,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy,
resourceVersion: queryArg.resourceVersion,
resourceVersionMatch: queryArg.resourceVersionMatch,
sendInitialEvents: queryArg.sendInitialEvents,
timeoutSeconds: queryArg.timeoutSeconds
}
}),
invalidatesTags: ["TimeInterval"]
}),
getTimeInterval: build.query({
query: (queryArg) => ({
url: `/timeintervals/${queryArg.name}`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["TimeInterval"]
}),
replaceTimeInterval: build.mutation({
query: (queryArg) => ({
url: `/timeintervals/${queryArg.name}`,
method: "PUT",
body: queryArg.timeInterval,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["TimeInterval"]
}),
deleteTimeInterval: build.mutation({
query: (queryArg) => ({
url: `/timeintervals/${queryArg.name}`,
method: "DELETE",
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
gracePeriodSeconds: queryArg.gracePeriodSeconds,
ignoreStoreReadErrorWithClusterBreakingPotential: queryArg.ignoreStoreReadErrorWithClusterBreakingPotential,
orphanDependents: queryArg.orphanDependents,
propagationPolicy: queryArg.propagationPolicy
}
}),
invalidatesTags: ["TimeInterval"]
}),
updateTimeInterval: build.mutation({
query: (queryArg) => ({
url: `/timeintervals/${queryArg.name}`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["TimeInterval"]
}),
getTimeIntervalStatus: build.query({
query: (queryArg) => ({
url: `/timeintervals/${queryArg.name}/status`,
params: {
pretty: queryArg.pretty
}
}),
providesTags: ["TimeInterval"]
}),
replaceTimeIntervalStatus: build.mutation({
query: (queryArg) => ({
url: `/timeintervals/${queryArg.name}/status`,
method: "PUT",
body: queryArg.timeInterval,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation
}
}),
invalidatesTags: ["TimeInterval"]
}),
updateTimeIntervalStatus: build.mutation({
query: (queryArg) => ({
url: `/timeintervals/${queryArg.name}/status`,
method: "PATCH",
body: queryArg.patch,
params: {
pretty: queryArg.pretty,
dryRun: queryArg.dryRun,
fieldManager: queryArg.fieldManager,
fieldValidation: queryArg.fieldValidation,
force: queryArg.force
}
}),
invalidatesTags: ["TimeInterval"]
})
}),
overrideExisting: false
});
;
const USER_DEFINED_TREE_NAME = "user-defined";
;
function matchLabels(matchers, labels) {
const matches = matchLabelsSet(matchers, labels);
const details = labels.map((_label, index) => ({
labelIndex: index,
match: false,
matcher: null
}));
matchers.forEach((matcher) => {
const matchingLabelIndex = labels.findIndex((label) => isLabelMatch(matcher, label));
if (matchingLabelIndex > -1) {
details[matchingLabelIndex].match = true;
details[matchingLabelIndex].matcher = matcher;
}
});
return { matches, details };
}
function isLabelMatch(matcher, label) {
const [labelKey, labelValue] = label;
const { label: matcherLabel, type: matcherType, value: matcherValue } = matcher;
if (labelKey !== matcherLabel) {
return false;
}
const matchFunction = OperatorFunctions[matcherType];
return matchFunction(labelValue, matcherValue);
}
function matchLabelsSet(matchers, labels) {
for (const matcher of matchers) {
if (!isLabelMatchInSet(matcher, labels)) {
return false;
}
}
return true;
}
function isLabelMatchInSet(matcher, labels) {
const { label, type, value } = matcher;
let labelValue = "";
const labelForMatcher = Object.fromEntries(labels)[label];
if (labelForMatcher) {
labelValue = labelForMatcher;
}
const matchFunction = OperatorFunctions[type];
try {
return matchFunction(labelValue, value);
} catch (err) {
return false;
}
}
const OperatorFunctions = {
"=": (lv, mv) => lv === mv,
"!=": (lv, mv) => lv !== mv,
// At the time of writing, Alertmanager compiles to another (anchored) Regular Expression,
// so we should also anchor our UI matches for consistency with this behaviour
// https://github.com/prometheus/alertmanager/blob/fd37ce9c95898ca68be1ab4d4529517174b73c33/pkg/labels/matcher.go#L69
"=~": (lv, mv) => {
const valueWithFlagsParsed = data.parseFlags(`^(?:${mv})$`);
const re = new RegExp(valueWithFlagsParsed.cleaned, valueWithFlagsParsed.flags);
return re.test(lv);
},
"!~": (lv, mv) => {
const valueWithFlagsParsed = data.parseFlags(`^(?:${mv})$`);
const re = new RegExp(valueWithFlagsParsed.cleaned, valueWithFlagsParsed.flags);
return !re.test(lv);
}
};
;
const INHERITABLE_KEYS = ["receiver", "group_by", "group_wait", "group_interval", "repeat_interval"];
function findMatchingRoutes(route, labels, matchingJourney = []) {
var _a;
let childMatches = [];
const matchResult = matchLabels((_a = route.matchers) != null ? _a : [], labels);
const currentMatchInfo = {
route,
matchDetails: matchResult.details,
matched: matchResult.matches
};
const currentMatchingJourney = [...matchingJourney, currentMatchInfo];
if (!matchResult.matches) {
return [];
}
if (route.routes) {
for (const child of route.routes) {
const matchingChildren = findMatchingRoutes(child, labels, currentMatchingJourney);
childMatches = childMatches.concat(matchingChildren);
if (matchingChildren.length && !child.continue) {
break;
}
}
}
if (childMatches.length === 0) {
childMatches.push({
route,
labels,
matchingJourney: currentMatchingJourney
});
}
return childMatches;
}
function computeInheritedTree(parent) {
var _a;
return {
...parent,
routes: (_a = parent.routes) == null ? void 0 : _a.map((child) => {
const inheritedProperties = getInheritedProperties(parent, child);
return computeInheritedTree({
...child,
...inheritedProperties
});
})
};
}
function getInheritedProperties(parentRoute, childRoute, propertiesParentInherited) {
const propsFromParent = lodash.pick(parentRoute, INHERITABLE_KEYS);
const inheritableProperties = {
...propsFromParent,
...propertiesParentInherited
};
const inherited = lodash.reduce(
inheritableProperties,
(inheritedProperties, parentValue, property) => {
var _a;
const parentHasValue = parentValue != null;
const inheritableValues = [void 0, "", null];
const childIsInheriting = inheritableValues.some((value) => childRoute[property] === value);
const inheritFromValue = childIsInheriting && parentHasValue;
const inheritEmptyGroupByFromParent = property === "group_by" && parentHasValue && lodash.isArray(childRoute[property]) && ((_a = childRoute[property]) == null ? void 0 : _a.length) === 0;
const inheritFromParent = inheritFromValue || inheritEmptyGroupByFromParent;
if (inheritFromParent) {
inheritedProperties[property] = parentValue;
}
return inheritedProperties;
},
{}
);
return inherited;
}
function addUniqueIdentifier(route) {
var _a, _b;
return {
id: lodash.uniqueId("route-"),
...route,
routes: (_b = (_a = route.routes) == null ? void 0 : _a.map(addUniqueIdentifier)) != null ? _b : []
};
}
function matchInstancesToRoute(rootRoute, instances) {
const matchedPolicies = /* @__PURE__ */ new Map();
const expandedTree = addUniqueIdentifier(computeInheritedTree(rootRoute));
const matchesArray = instances.flatMap((labels) => findMatchingRoutes(expandedTree, labels));
const groupedByRoute = lodash.groupBy(matchesArray, (match) => match.route.id);
Object.entries(groupedByRoute).forEach(([_key, match]) => {
matchedPolicies.set(match[0].route, match);
});
return {
expandedTree,
matchedPolicies
};
}
function convertRoutingTreeToRoute(routingTree) {
const convertRoutingTreeRoutes = (routes) => {
return routes.map(
(route) => ({
...route,
routes: route.routes ? convertRoutingTreeRoutes(route.routes) : []
})
);
};
const rootRoute = {
...routingTree.spec.defaults,
continue: false,
active_time_intervals: [],
mute_time_intervals: [],
matchers: [],
// Root route has no matchers (catch-all)
routes: convertRoutingTreeRoutes(routingTree.spec.routes)
};
return rootRoute;
}
;
function useMatchInstancesToRouteTrees() {
const { data, ...rest } = injectedRtkApi.endpoints.listRoutingTree.useQuery(
{},
{
refetchOnFocus: true,
refetchOnReconnect: true
}
);
const memoizedFunction = react.useCallback(
(instances) => {
var _a;
return matchInstancesToRouteTrees((_a = data == null ? void 0 : data.items) != null ? _a : [], instances);
},
[data == null ? void 0 : data.items]
);
return {
matchInstancesToRouteTrees: memoizedFunction,
...rest
};
}
function matchInstancesToRouteTrees(trees, instances) {
const treeMatches = trees.map((tree) => {
const rootRoute = convertRoutingTreeToRoute(tree);
return matchInstancesToRoute(rootRoute, instances);
});
return instances.map((labels) => {
const allMatchedRoutes = treeMatches.flatMap(({ expandedTree, matchedPolicies }, index) => {
const tree = trees[index];
return Array.from(matchedPolicies.entries()).flatMap(
([route, results]) => results.filter((matchDetails) => matchDetails.labels === labels).map((matchDetails) => {
var _a;
return {
route,
routeTree: {
metadata: { name: (_a = tree.metadata.name) != null ? _a : USER_DEFINED_TREE_NAME },
expandedSpec: expandedTree
},
matchDetails
};
})
);
});
return {
labels,
matchedRoutes: allMatchedRoutes
};
});
}
;
;
exports.AlertLabel = AlertLabel;
exports.AlertLabels = AlertLabels;
exports.USER_DEFINED_TREE_NAME = USER_DEFINED_TREE_NAME;
exports.base64UrlEncode = base64UrlEncode;
exports.computeInheritedTree = computeInheritedTree;
exports.findMatchingRoutes = findMatchingRoutes;
exports.getInheritedProperties = getInheritedProperties;
exports.matchInstancesToRoute = matchInstancesToRoute;
exports.matchInstancesToRouteTrees = matchInstancesToRouteTrees;
exports.useMatchInstancesToRouteTrees = useMatchInstancesToRouteTrees;
//# sourceMappingURL=index.cjs.map