added grafana module
This commit is contained in:
parent
878ecba717
commit
7c9e84971e
38 changed files with 583 additions and 0 deletions
4
grafana/README.md
Normal file
4
grafana/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Modules for Grafana alerts and dashboards
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
TODO
|
||||||
3
grafana/alert-folder/output.tf
Normal file
3
grafana/alert-folder/output.tf
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
output "folder_uid" {
|
||||||
|
value = grafana_folder.this.uid
|
||||||
|
}
|
||||||
8
grafana/alert-folder/providers.tf
Normal file
8
grafana/alert-folder/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
grafana/alert-folder/rule-folder.tf
Normal file
3
grafana/alert-folder/rule-folder.tf
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
resource "grafana_folder" "this" {
|
||||||
|
title = var.alert-folder
|
||||||
|
}
|
||||||
6
grafana/alert-folder/variables.tf
Normal file
6
grafana/alert-folder/variables.tf
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Alert Rule Folder
|
||||||
|
variable "alert-folder" {
|
||||||
|
description = "folder name to group alerts"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
77
grafana/alert-group/alert-group.tf
Normal file
77
grafana/alert-group/alert-group.tf
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
resource "grafana_rule_group" "this" {
|
||||||
|
name = var.group_name
|
||||||
|
folder_uid = var.folder_uid
|
||||||
|
interval_seconds = 60
|
||||||
|
org_id = 1
|
||||||
|
disable_provenance = true
|
||||||
|
|
||||||
|
rule {
|
||||||
|
name = "test-alert"
|
||||||
|
for = "1m"
|
||||||
|
condition = "C"
|
||||||
|
no_data_state = "NoData"
|
||||||
|
exec_err_state = "Error"
|
||||||
|
is_paused = false
|
||||||
|
annotations = {
|
||||||
|
"description" = "Pod `{{ $labels.namespace }}/{{ $labels.pod }}` is crash looping"
|
||||||
|
"summary" = "Kubernetes pod crash looping (instance {{ $labels.instance }})"
|
||||||
|
}
|
||||||
|
|
||||||
|
data {
|
||||||
|
ref_id = "A"
|
||||||
|
query_type = ""
|
||||||
|
relative_time_range {
|
||||||
|
from = 600
|
||||||
|
to = 0
|
||||||
|
}
|
||||||
|
datasource_uid = var.datasource_uid
|
||||||
|
model = jsonencode({
|
||||||
|
intervalMs = 1000
|
||||||
|
maxDataPoints = 43200
|
||||||
|
refId = "A"
|
||||||
|
expr = "increase(kube_pod_container_status_restarts_total{}[1h]) > 3"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
data {
|
||||||
|
ref_id = "C"
|
||||||
|
relative_time_range {
|
||||||
|
from = 0
|
||||||
|
to = 0
|
||||||
|
}
|
||||||
|
datasource_uid = var.datasource_uid
|
||||||
|
model = <<EOT
|
||||||
|
{
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"evaluator": {
|
||||||
|
"params": [0],
|
||||||
|
"type": "gt"
|
||||||
|
},
|
||||||
|
"operator": {
|
||||||
|
"type": "and"
|
||||||
|
},
|
||||||
|
"query": {
|
||||||
|
"params": ["C"]
|
||||||
|
},
|
||||||
|
"reducer": {
|
||||||
|
"params": [],
|
||||||
|
"type": "last"
|
||||||
|
},
|
||||||
|
"type": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"datasource": {
|
||||||
|
"type": "__expr__",
|
||||||
|
"uid": "__expr__"
|
||||||
|
},
|
||||||
|
"expression": "A",
|
||||||
|
"intervalMs": 1000,
|
||||||
|
"maxDataPoints": 43200,
|
||||||
|
"refId": "C",
|
||||||
|
"type": "threshold"
|
||||||
|
}
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
grafana/alert-group/providers.tf
Normal file
9
grafana/alert-group/providers.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
19
grafana/alert-group/variables.tf
Normal file
19
grafana/alert-group/variables.tf
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
variable "group_name" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "folder_uid" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "datasource_uid" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "rule_name" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "condition" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
46
grafana/alerts/locals.tf
Normal file
46
grafana/alerts/locals.tf
Normal 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
51
grafana/alerts/main.tf
Normal 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
4
grafana/alerts/output.tf
Normal 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 }
|
||||||
|
}
|
||||||
8
grafana/alerts/providers.tf
Normal file
8
grafana/alerts/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
grafana/alerts/variables.tf
Normal file
38
grafana/alerts/variables.tf
Normal 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)."
|
||||||
|
}
|
||||||
9
grafana/contact-point-gchat/main.tf
Normal file
9
grafana/contact-point-gchat/main.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
resource "grafana_contact_point" "this" {
|
||||||
|
name = var.contact-point-name
|
||||||
|
|
||||||
|
googlechat {
|
||||||
|
url = var.google-chat-url
|
||||||
|
message = "{{ template \"google-chat-body-template\" . }}"
|
||||||
|
title = "{{ template \"google-chat-title-template\" . }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
grafana/contact-point-gchat/output.tf
Normal file
8
grafana/contact-point-gchat/output.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
output "contact_name" {
|
||||||
|
value = grafana_contact_point.this.name
|
||||||
|
description = "UID of the created contact point"
|
||||||
|
}
|
||||||
|
output "contact_id" {
|
||||||
|
value = grafana_contact_point.this.id
|
||||||
|
description = "UID of the created contact point"
|
||||||
|
}
|
||||||
8
grafana/contact-point-gchat/providers.tf
Normal file
8
grafana/contact-point-gchat/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
grafana/contact-point-gchat/variables.tf
Normal file
11
grafana/contact-point-gchat/variables.tf
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Grafana contact point
|
||||||
|
variable "google-chat-url" {
|
||||||
|
description = "google-chat-webhook url"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "contact-point-name" {
|
||||||
|
description = "google-chat-contact-point-name"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
9
grafana/contact-point-opsgenie-heartbeat/main.tf
Normal file
9
grafana/contact-point-opsgenie-heartbeat/main.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
resource "grafana_contact_point" "this" {
|
||||||
|
name = var.contact_point_name
|
||||||
|
disable_provenance = var.disable_provenance
|
||||||
|
|
||||||
|
webhook {
|
||||||
|
url = "${var.webhook_url}?apiKey=${var.opsgenie_api_key}"
|
||||||
|
http_method = var.http_method
|
||||||
|
}
|
||||||
|
}
|
||||||
9
grafana/contact-point-opsgenie-heartbeat/output.tf
Normal file
9
grafana/contact-point-opsgenie-heartbeat/output.tf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
output "contact_name" {
|
||||||
|
value = grafana_contact_point.this.name
|
||||||
|
description = "Receiver name of the webhook contact-point."
|
||||||
|
}
|
||||||
|
|
||||||
|
output "contact_id" {
|
||||||
|
value = grafana_contact_point.this.id
|
||||||
|
description = "Internal Grafana ID of the contact-point."
|
||||||
|
}
|
||||||
8
grafana/contact-point-opsgenie-heartbeat/providers.tf
Normal file
8
grafana/contact-point-opsgenie-heartbeat/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
grafana/contact-point-opsgenie-heartbeat/variables.tf
Normal file
27
grafana/contact-point-opsgenie-heartbeat/variables.tf
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
variable "contact_point_name" {
|
||||||
|
description = "Name of the webhook contact point"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "webhook_url" {
|
||||||
|
description = "Base URL (e.g., https://api.eu.opsgenie.com/v2/heartbeats/<name>/ping)"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "opsgenie_api_key" {
|
||||||
|
description = "OpsGenie API key"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "http_method" {
|
||||||
|
description = "HTTP method for webhook"
|
||||||
|
type = string
|
||||||
|
default = "POST"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disable_provenance" {
|
||||||
|
description = "Disable provenance"
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
11
grafana/contact-point-opsgenie/main.tf
Normal file
11
grafana/contact-point-opsgenie/main.tf
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
resource "grafana_contact_point" "this" {
|
||||||
|
name = var.contact_point_name
|
||||||
|
disable_provenance = var.disable_provenance
|
||||||
|
|
||||||
|
opsgenie {
|
||||||
|
api_key = var.opsgenie_api_key
|
||||||
|
url = var.opsgenie_url
|
||||||
|
override_priority = var.override_priority
|
||||||
|
auto_close = var.auto_close
|
||||||
|
}
|
||||||
|
}
|
||||||
8
grafana/contact-point-opsgenie/output.tf
Normal file
8
grafana/contact-point-opsgenie/output.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
output "contact_name" {
|
||||||
|
value = grafana_contact_point.this.name
|
||||||
|
description = "UID of the created contact point"
|
||||||
|
}
|
||||||
|
output "contact_id" {
|
||||||
|
value = grafana_contact_point.this.id
|
||||||
|
description = "UID of the created contact point"
|
||||||
|
}
|
||||||
8
grafana/contact-point-opsgenie/providers.tf
Normal file
8
grafana/contact-point-opsgenie/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
grafana/contact-point-opsgenie/variables.tf
Normal file
37
grafana/contact-point-opsgenie/variables.tf
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
########################################
|
||||||
|
# Required
|
||||||
|
########################################
|
||||||
|
variable "contact_point_name" {
|
||||||
|
description = "Name of the Opsgenie contact point (receiver) in Grafana"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "opsgenie_api_key" {
|
||||||
|
description = "Opsgenie API key"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disable_provenance" {
|
||||||
|
description = "Set to true to disable provenance on the contact-point"
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "opsgenie_url" {
|
||||||
|
description = "Base URL for the Opsgenie API (change for US vs EU)"
|
||||||
|
type = string
|
||||||
|
default = "https://api.eu.opsgenie.com/v2/alerts"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "override_priority" {
|
||||||
|
description = "Whether Opsgenie should override alert priority"
|
||||||
|
type = bool
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "auto_close" {
|
||||||
|
description = "Whether to auto-close alerts in OpsGenie when they resolve in the Alertmanager"
|
||||||
|
type = bool
|
||||||
|
default = true
|
||||||
|
}
|
||||||
11
grafana/datasource/datasource.tf
Normal file
11
grafana/datasource/datasource.tf
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
resource "grafana_data_source" "this" {
|
||||||
|
type = "prometheus"
|
||||||
|
name = var.datasource_name
|
||||||
|
url = var.datasource_url
|
||||||
|
basic_auth_enabled = true
|
||||||
|
basic_auth_username = var.datasource_username
|
||||||
|
|
||||||
|
secure_json_data_encoded = jsonencode({
|
||||||
|
basicAuthPassword = var.datasource_password
|
||||||
|
})
|
||||||
|
}
|
||||||
3
grafana/datasource/output.tf
Normal file
3
grafana/datasource/output.tf
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
output "datasource_uid" {
|
||||||
|
value = grafana_data_source.this.uid
|
||||||
|
}
|
||||||
8
grafana/datasource/providers.tf
Normal file
8
grafana/datasource/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
grafana/datasource/variables.tf
Normal file
18
grafana/datasource/variables.tf
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Grafana contact point
|
||||||
|
variable "datasource_url" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "datasource_name" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "datasource_username" {
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "datasource_password" {
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
7
grafana/message-template/message-template.tf
Normal file
7
grafana/message-template/message-template.tf
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
resource "grafana_message_template" "this" {
|
||||||
|
for_each = local.templates
|
||||||
|
|
||||||
|
name = each.key
|
||||||
|
template = each.value.content
|
||||||
|
disable_provenance = var.disable_provenance
|
||||||
|
}
|
||||||
4
grafana/message-template/outputs.tf
Normal file
4
grafana/message-template/outputs.tf
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
output "template_ids" {
|
||||||
|
description = "Map of template-group name → Grafana UID"
|
||||||
|
value = { for k, v in grafana_message_template.this : k => v.id }
|
||||||
|
}
|
||||||
8
grafana/message-template/providers.tf
Normal file
8
grafana/message-template/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
grafana/message-template/templates.tf
Normal file
17
grafana/message-template/templates.tf
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
locals {
|
||||||
|
# 1. Collect every matching file – paths are relative to templates_dir
|
||||||
|
template_files = fileset(
|
||||||
|
"${path.root}/${var.templates_dir}",
|
||||||
|
var.file_pattern
|
||||||
|
)
|
||||||
|
|
||||||
|
# 2. Build a map: group-name → { content = <file-text> }
|
||||||
|
# We strip the extension to get a neat group name.
|
||||||
|
templates = {
|
||||||
|
for rel_path in local.template_files :
|
||||||
|
trimsuffix(basename(rel_path), ".tmpl") =>
|
||||||
|
{
|
||||||
|
content = file("${path.root}/${var.templates_dir}/${rel_path}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
grafana/message-template/variables.tf
Normal file
17
grafana/message-template/variables.tf
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
variable "templates_dir" {
|
||||||
|
description = "Relative path (from the root module) that holds all *.go or *.tmpl template files."
|
||||||
|
type = string
|
||||||
|
default = "templates"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "file_pattern" {
|
||||||
|
description = "Glob pattern for template files inside templates_dir."
|
||||||
|
type = string
|
||||||
|
default = "*.tmpl" # change to *.tmpl if you prefer
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disable_provenance" {
|
||||||
|
description = "Leave templates editable in Grafana UI."
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
18
grafana/notification-policy/main.tf
Normal file
18
grafana/notification-policy/main.tf
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
resource "grafana_notification_policy" "this" {
|
||||||
|
contact_point = var.default_contact_point_uid
|
||||||
|
group_by = var.group_by
|
||||||
|
|
||||||
|
dynamic "policy" {
|
||||||
|
for_each = var.folder_policies
|
||||||
|
content {
|
||||||
|
matcher {
|
||||||
|
label = "grafana_folder"
|
||||||
|
match = "="
|
||||||
|
value = policy.key # folder title, e.g. "Test-Alerts"
|
||||||
|
}
|
||||||
|
|
||||||
|
contact_point = policy.value
|
||||||
|
repeat_interval = "1h"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
grafana/notification-policy/output.tf
Normal file
4
grafana/notification-policy/output.tf
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
output "policy_id" {
|
||||||
|
description = "ID of the notification policy resource"
|
||||||
|
value = grafana_notification_policy.this.id
|
||||||
|
}
|
||||||
8
grafana/notification-policy/providers.tf
Normal file
8
grafana/notification-policy/providers.tf
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
grafana = {
|
||||||
|
source = "grafana/grafana"
|
||||||
|
version = "= 3.25.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
grafana/notification-policy/variables.tf
Normal file
31
grafana/notification-policy/variables.tf
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
variable "group_by" {
|
||||||
|
description = "Labels to group alerts by before routing. Grafana default is [\"alertname\"]."
|
||||||
|
type = list(string)
|
||||||
|
default = ["alertname"]
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "default_contact_point_uid" {
|
||||||
|
description = "Fallback contact-point UID for alerts that match no folder-specific policy."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "folder_policies" {
|
||||||
|
description = <<-EOT
|
||||||
|
Map of folder UID → contact-point UID.
|
||||||
|
Each entry creates a matcher block:
|
||||||
|
|
||||||
|
policy {
|
||||||
|
matcher { label = "folder"; match = <folder_uid> }
|
||||||
|
contact_point = <contact_point_uid>
|
||||||
|
}
|
||||||
|
EOT
|
||||||
|
type = map(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
variable "folder_label_key" {
|
||||||
|
description = "Label key used to match alert folders (e.g., 'folder' or 'namespace_uid')"
|
||||||
|
type = string
|
||||||
|
default = "folder"
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in a new issue