added grafana module

This commit is contained in:
Stanislav Kopp 2025-07-10 11:28:59 +02:00
parent 878ecba717
commit 7c9e84971e
38 changed files with 583 additions and 0 deletions

46
grafana/alerts/locals.tf Normal file
View file

@ -0,0 +1,46 @@
locals {
#################################################################
# 1. Discover & decode alert YAML files from <root>/<alerts_dir>
#################################################################
alert_files = fileset(
"${path.root}/${var.alerts_dir}",
var.file_pattern
)
decoded_files = [
for f in local.alert_files :
yamldecode(file("${path.root}/${var.alerts_dir}/${f}"))
]
#################################################################
# 2. Flatten: each file may contain multiple groups
#################################################################
groups_raw = flatten([
for doc in local.decoded_files : try(doc.groups, [])
])
#################################################################
# 3. Merge defaults & convert camelCase snake_case
#################################################################
groups = [
for g in local.groups_raw : merge(g, {
uid = try(
g.uid,
trim(replace(replace(lower(g.name), " ", "-"), "_", "-"), "-")
)
folder_uid = try(try(g.folder_uid, g.folder), var.default_folder_uid)
interval = try(g.interval, "1m")
rules = [
for r in g.rules : merge(r, {
data = [
for d in r.data : merge(d, {
datasource_uid = try(d.datasourceUid, var.default_datasource_uid)
relative_time_range = try(d.relativeTimeRange, { from = 600, to = 0 })
})
]
})
]
})
]
}

51
grafana/alerts/main.tf Normal file
View file

@ -0,0 +1,51 @@
resource "grafana_rule_group" "this" {
for_each = {
for g in local.groups :
g.uid => g
}
name = each.value.name
folder_uid = each.value.folder_uid
interval_seconds = (
substr(each.value.interval, length(each.value.interval) - 1, 1) == "m"
? tonumber(substr(each.value.interval, 0, length(each.value.interval) - 1)) * 60
: tonumber(trim(each.value.interval, "s"))
)
disable_provenance = var.disable_provenance
dynamic "rule" {
for_each = each.value.rules
content {
uid = rule.value.uid
name = try(rule.value.title, rule.value.name)
condition = rule.value.condition
no_data_state = rule.value.noDataState
exec_err_state = rule.value.execErrState
is_paused = try(rule.value.isPaused, false)
for = try(rule.value.for, null)
labels = try(rule.value.labels, {})
dynamic "data" {
for_each = rule.value.data
content {
ref_id = data.value.refId
datasource_uid = data.value.datasource_uid
dynamic "relative_time_range" {
for_each = [data.value.relative_time_range]
content {
from = relative_time_range.value.from
to = relative_time_range.value.to
}
}
model = jsonencode(data.value.model)
}
}
}
}
}

4
grafana/alerts/output.tf Normal file
View file

@ -0,0 +1,4 @@
output "rule_group_ids" {
description = "Map: <folder_uid>.<name> → Grafana rule-group ID"
value = { for k, v in grafana_rule_group.this : k => v.id }
}

View file

@ -0,0 +1,8 @@
terraform {
required_providers {
grafana = {
source = "grafana/grafana"
version = "= 3.25.4"
}
}
}

View file

@ -0,0 +1,38 @@
variable "alerts_dir" {
type = string
default = "alerts"
description = "Relative path to the directory containing alert rule YAML files."
}
variable "file_pattern" {
type = string
default = "*.y{a,}ml"
description = "Glob pattern to match alert rule YAML files (e.g. *.yaml, *.yml)."
}
variable "default_datasource_uid" {
type = string
description = "UID of the Prometheus or Thanos datasource to use if not specified in the alert rule."
}
variable "default_receiver" {
type = string
description = "Name of the contact point (receiver) to use for notifications if not defined in alert rule."
}
variable "default_folder_uid" {
type = string
description = "UID of the Grafana folder to use for alert rules when not defined in the YAML."
}
variable "default_interval_seconds" {
type = number
default = 60
description = "Default evaluation interval (in seconds) for alert rule groups if not set in YAML."
}
variable "disable_provenance" {
type = bool
default = false
description = "If true, disables Grafana alert provisioning provenance (sets disable_provenance = true)."
}