Skip to content
Snippets Groups Projects
Commit 72132aa5 authored by Haoyu Sun's avatar Haoyu Sun
Browse files

add rule patching function

parent 805f875f
Branches
No related tags found
No related merge requests found
local kp =
(import 'kube-prometheus/main.libsonnet') +
{
values+:: {
common+: {
namespace: 'monitoring',
},
},
};
local rulePatches = import 'rule-patches.libsonnet';
local sanitizePrometheusRules = (import 'kube-prometheus/lib/rule-sanitizer.libsonnet')(rulePatches).sanitizePrometheusRules;
sanitizePrometheusRules({ 'setup/0namespace-namespace': kp.kubePrometheus.namespace } +
{
['setup/prometheus-operator-' + name]: kp.prometheusOperator[name]
for name in std.filter((function(name) name != 'serviceMonitor' && name != 'prometheusRule'), std.objectFields(kp.prometheusOperator))
} +
// serviceMonitor and prometheusRule are separated so that they can be created after the CRDs are ready
{ 'prometheus-operator-serviceMonitor': kp.prometheusOperator.serviceMonitor } +
{ 'prometheus-operator-prometheusRule': kp.prometheusOperator.prometheusRule } +
{ 'kube-prometheus-prometheusRule': kp.kubePrometheus.prometheusRule } +
{ ['alertmanager-' + name]: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } +
{ ['blackbox-exporter-' + name]: kp.blackboxExporter[name] for name in std.objectFields(kp.blackboxExporter) } +
{ ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) } +
{ ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } +
{ ['kubernetes-' + name]: kp.kubernetesControlPlane[name] for name in std.objectFields(kp.kubernetesControlPlane) }
{ ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } +
{ ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } +
{ ['prometheus-adapter-' + name]: kp.prometheusAdapter[name] for name in std.objectFields(kp.prometheusAdapter) })
{
excludedRuleGroups: [
'alertmanager.rules',
],
excludedRules: [
{
name: 'prometheus-operator',
rules: [
{ alert: 'PrometheusOperatorListErrors' },
],
},
],
patchedRules: [
{
name: 'prometheus-operator',
rules: [
{
alert: 'PrometheusOperatorWatchErrors',
labels: {
severity: 'info',
},
},
],
},
],
}
local defaults = {
/* name of rule groups to exclude */
excludedRuleGroups: [],
/* Rule match is based on field "alert" or "record" for excludedRules and patchedRules.
* When multiple match is found, we can use a "index" field to distingush each rule,
* which represents their order of appearance. For example, if we have two rules:
* [
* {
* name: 'alertmanager.rules',
* rules: [
* {
* alert: 'A',
* field: 'A0 rule',
* labels: {
* severity: 'warning',
* },
* },
* {
* alert: 'A',
* field: 'A1 rule',
* labels: {
* severity: 'warning',
* },
* },
* ],
* },
* ]
* We can use index 1 to choose "A1 rule" for patching, as shown in the example below:
* [
* {
* name: 'alertmanager.rules',
* rules: [
* {
* alert: 'A',
* index: 1,
* patch: 'A1',
* labels: {
* severity: 'warning',
* },
* },
* ],
* },
* ]
*/
excludedRules: [],
patchedRules: [],
};
local deleteIndex(rule) = {
[k]: rule[k]
for k in std.objectFields(rule)
if k != 'index'
};
local patchOrExcludeRule(rule, ruleSet, operation) =
if std.length(ruleSet) == 0 then
[deleteIndex(rule)]
/* 2 rules match when the name of the patch is a prefix of the name of the rule to patch. */
else if ((('alert' in rule && 'alert' in ruleSet[0]) && std.startsWith(rule.alert, ruleSet[0].alert)) ||
(('record' in rule && 'record' in ruleSet[0]) && std.startsWith(rule.record, ruleSet[0].record))) &&
(!('index' in ruleSet[0]) || (('index' in ruleSet[0]) && (ruleSet[0].index == rule.index))) then
if operation == 'patch' then
local patch = {
[k]: ruleSet[0][k]
for k in std.objectFields(ruleSet[0])
if k != 'alert' && k != 'record' && k != 'index'
};
[deleteIndex(std.mergePatch(rule, patch))]
else // equivalnt to operation == 'exclude'
[]
else
[] + patchOrExcludeRule(rule, ruleSet[1:], operation);
local sameRuleName(rule1, rule2) =
if ('alert' in rule1 && 'alert' in rule2) then
rule1.alert == rule2.alert
else if ('record' in rule1 && 'record' in rule2) then
rule1.record == rule2.record
else
false;
local indexRules(lastRule, ruleSet) =
if std.length(ruleSet) == 0 then
[]
else if (lastRule != null) && sameRuleName(lastRule, ruleSet[0]) then
local updatedRule = std.mergePatch(ruleSet[0], { index: lastRule.index + 1 });
[updatedRule] + indexRules(updatedRule, ruleSet[1:])
else
local updatedRule = std.mergePatch(ruleSet[0], { index: 0 });
[updatedRule] + indexRules(updatedRule, ruleSet[1:]);
local ruleName(rule) =
if ('alert' in rule) then
rule.alert
else if ('record' in rule) then
rule.record
else
assert false : 'rule should have either "alert" or "record" field' + std.toString(rule);
'';
local patchOrExcludeRuleGroup(group, groupSet, operation) =
if std.length(groupSet) == 0 then
[group.rules]
else if (group.name == groupSet[0].name) then
local indexedRules = indexRules(null, std.sort(
group.rules, keyF=ruleName
));
[patchOrExcludeRule(rule, groupSet[0].rules, operation) for rule in indexedRules]
else
[] + patchOrExcludeRuleGroup(group, groupSet[1:], operation);
function(params) {
local ruleModifications = defaults + params,
assert std.isArray(ruleModifications.excludedRuleGroups) : 'rule-patcher: excludedRuleGroups should be an array',
assert std.isArray(ruleModifications.excludedRules) : 'rule-patcher: excludedRules should be an array',
assert std.isArray(ruleModifications.patchedRules) : 'rule-patcher: patchedRules should be an array',
local excludeRule(o) = o {
[if (o.kind == 'PrometheusRule') then 'spec']+: {
groups: std.filterMap(
function(group) !std.member(ruleModifications.excludedRuleGroups, group.name),
function(group)
group {
rules: std.flattenArrays(
patchOrExcludeRuleGroup(group, ruleModifications.excludedRules, 'exclude')
),
},
super.groups,
),
},
},
local patchRule(o) = o {
[if (o.kind == 'PrometheusRule') then 'spec']+: {
groups: std.map(
function(group)
group {
rules: std.flattenArrays(
patchOrExcludeRuleGroup(group, ruleModifications.patchedRules, 'patch')
),
},
super.groups,
),
},
},
// shorthand for rule patching, rule excluding
sanitizePrometheusRules(o): {
[k]: patchRule(excludeRule(o[k]))
for k in std.objectFields(o)
},
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment