From 7413af8b2bdf5edfa349ae34428bdaa3bb0c4c08 Mon Sep 17 00:00:00 2001 From: Stanislav Kopp Date: Tue, 5 Aug 2025 16:40:48 +0200 Subject: [PATCH] updated grafana modules --- grafana/README.md | 10 ++--- grafana/Untitled111.md | 1 + grafana/alerts/locals.tf | 37 +++++++++-------- grafana/alerts/main.tf | 10 ++--- grafana/alerts/output.tf | 7 ++++ grafana/alerts/variables.tf | 22 ++++------ grafana/contact-point-gchat/main.tf | 10 ++--- grafana/contact-point-gchat/output.tf | 14 +++++-- grafana/contact-point-gchat/templates.tf | 24 +++++++++++ grafana/contact-point-gchat/variables.tf | 37 +++++++++++++---- grafana/datasource/datasource.tf | 18 +++++--- grafana/datasource/output.tf | 5 ++- grafana/datasource/variables.tf | 41 +++++++++++++------ .../templates/google-chat-body-template.tmpl | 2 +- .../templates/google-chat-title-template.tmpl | 2 +- 15 files changed, 159 insertions(+), 81 deletions(-) create mode 100644 grafana/Untitled111.md create mode 100644 grafana/contact-point-gchat/templates.tf diff --git a/grafana/README.md b/grafana/README.md index b9f995b..b129b6a 100644 --- a/grafana/README.md +++ b/grafana/README.md @@ -20,9 +20,9 @@ module "datasource" { } # Alert Receiver / Contact Point -module "gchat-contact-point" { +module "google-chat-contact-point" { source = "git::https://commerce-platform.git.onstackit.cloud/commerce-platform-public/terraform-modules//grafana/contact-point-gchat?ref=main" - gchat-url = var.google_chat_url + google-chat-url = var.google_chat_url contact-point-name = "gchat" } @@ -45,11 +45,11 @@ module "message-templates" { module "notification-policy" { source = "git::https://commerce-platform.git.onstackit.cloud/commerce-platform-public/terraform-modules//grafana/notification-policy?ref=main" - default_contact_point_uid = module.gchat-contact-point.contact_name + default_contact_point_uid = module.google-chat-contact-point.contact_name group_by = ["alertname"] folder_policies = { - "Alerts" = module.gchat-contact-point.contact_name + "Alerts" = module.google-chat-contact-point.contact_name } } @@ -59,7 +59,7 @@ module "alerting" { alerts_dir = "alerts" default_datasource_uid = module.datasource.datasource_uid - default_receiver = module.gchat-contact-point.contact_name + default_receiver = module.google-chat-contact-point.contact_name default_folder_uid = module.alert-folder.folder_uid default_interval_seconds = 60 disable_provenance = true diff --git a/grafana/Untitled111.md b/grafana/Untitled111.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/grafana/Untitled111.md @@ -0,0 +1 @@ + diff --git a/grafana/alerts/locals.tf b/grafana/alerts/locals.tf index e685468..322654b 100644 --- a/grafana/alerts/locals.tf +++ b/grafana/alerts/locals.tf @@ -1,10 +1,8 @@ locals { - ################################################################# - # 1. Discover & decode alert YAML files from / - ################################################################# + # 1. Find and decode YAML files alert_files = fileset( "${path.root}/${var.alerts_dir}", - var.file_pattern + "**/*.yaml" ) decoded_files = [ @@ -12,31 +10,36 @@ locals { yamldecode(file("${path.root}/${var.alerts_dir}/${f}")) ] - ################################################################# - # 2. Flatten: each file may contain multiple groups - ################################################################# + # 2. Flatten: each YAML may define multiple groups groups_raw = flatten([ for doc in local.decoded_files : try(doc.groups, []) ]) - ################################################################# - # 3. Merge defaults & convert camelCase → snake_case - ################################################################# + # 3. Inject defaults (datasource, folder, interval) and sanitize models 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") + uid = try(g.uid, lower(replace(g.name, " ", "-"))) + folder_uid = var.folder_uid + interval = try(g.interval, "${var.default_interval_seconds}s") 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) + # Preserve __expr__ for expressions, otherwise inject default UID + datasource_uid = ( + try(d.datasourceUid, "") == "__expr__" + ? "__expr__" + : var.datasource_uid + ) + relative_time_range = try(d.relativeTimeRange, { from = 600, to = 0 }) + + # Sanitize model: remove keys Grafana ignores to prevent plan drift + model = { + for k, v in d.model : k => v + if !(k == "queryType" || k == "query_type") + } }) ] }) diff --git a/grafana/alerts/main.tf b/grafana/alerts/main.tf index 5a1a078..837664f 100644 --- a/grafana/alerts/main.tf +++ b/grafana/alerts/main.tf @@ -1,8 +1,5 @@ resource "grafana_rule_group" "this" { - for_each = { - for g in local.groups : - g.uid => g - } + for_each = { for g in local.groups : g.uid => g } name = each.value.name folder_uid = each.value.folder_uid @@ -21,14 +18,15 @@ resource "grafana_rule_group" "this" { uid = rule.value.uid name = try(rule.value.title, rule.value.name) condition = rule.value.condition + for = try(rule.value.for, null) 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, {}) + # Merge team labels with platform-injected receiver annotations = try(rule.value.annotations, {}) + labels = try(rule.value.labels, {}) dynamic "data" { for_each = rule.value.data diff --git a/grafana/alerts/output.tf b/grafana/alerts/output.tf index af60ede..facf109 100644 --- a/grafana/alerts/output.tf +++ b/grafana/alerts/output.tf @@ -2,3 +2,10 @@ output "rule_group_ids" { description = "Map: . → Grafana rule-group ID" value = { for k, v in grafana_rule_group.this : k => v.id } } +output "debug_alert_files" { + value = local.alert_files +} +output "debug_groups" { + description = "Parsed groups from YAML" + value = local.groups +} \ No newline at end of file diff --git a/grafana/alerts/variables.tf b/grafana/alerts/variables.tf index 345bfda..34d8f20 100644 --- a/grafana/alerts/variables.tf +++ b/grafana/alerts/variables.tf @@ -4,35 +4,29 @@ variable "alerts_dir" { description = "Relative path to the directory containing alert rule YAML files." } -variable "file_pattern" { +variable "datasource_uid" { + description = "Grafana datasource UID to apply to all alerts in this module" type = string - default = "*.y{a,}ml" - description = "Glob pattern to match alert rule YAML files (e.g. *.yaml, *.yml)." } -variable "default_datasource_uid" { +variable "folder_uid" { + description = "Grafana folder UID where alerts will be placed" type = string - description = "UID of the Prometheus or Thanos datasource to use if not specified in the alert rule." } -variable "default_receiver" { +variable "receiver" { + description = "Contact point name to associate with alerts" 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" { + description = "Default evaluation interval (in seconds)" type = number default = 60 - description = "Default evaluation interval (in seconds) for alert rule groups if not set in YAML." } variable "disable_provenance" { + description = "Disable provenance flag for imported alerts" type = bool default = false - description = "If true, disables Grafana alert provisioning provenance (sets disable_provenance = true)." } \ No newline at end of file diff --git a/grafana/contact-point-gchat/main.tf b/grafana/contact-point-gchat/main.tf index eb21706..bed73bf 100644 --- a/grafana/contact-point-gchat/main.tf +++ b/grafana/contact-point-gchat/main.tf @@ -1,9 +1,9 @@ resource "grafana_contact_point" "this" { - name = var.contact-point-name + name = var.contact_point_name googlechat { - url = var.gchat-url - message = "{{ template \"gchat-body-template\" . }}" - title = "{{ template \"gchat-title-template\" . }}" + url = var.gchat_url + message = "{{ template \"${var.template_prefix}gchat-body-template\" . }}" + title = "{{ template \"${var.template_prefix}gchat-title-template\" . }}" } -} \ No newline at end of file +} diff --git a/grafana/contact-point-gchat/output.tf b/grafana/contact-point-gchat/output.tf index 8600044..6f049c6 100644 --- a/grafana/contact-point-gchat/output.tf +++ b/grafana/contact-point-gchat/output.tf @@ -1,8 +1,14 @@ -output "contact_name" { +output "contact_point_name" { value = grafana_contact_point.this.name - description = "UID of the created contact point" + description = "Name of the created contact point" } -output "contact_id" { + +output "contact_point_id" { value = grafana_contact_point.this.id - description = "UID of the created contact point" + description = "ID of the created contact point" +} + +output "template_names" { + value = [for t in grafana_message_template.templates : t.name] + description = "List of message template names created by this module" } diff --git a/grafana/contact-point-gchat/templates.tf b/grafana/contact-point-gchat/templates.tf new file mode 100644 index 0000000..f547011 --- /dev/null +++ b/grafana/contact-point-gchat/templates.tf @@ -0,0 +1,24 @@ +locals { + # Collect template files relative to root + template_files = fileset( + "${path.root}/${var.templates_dir}", + var.file_pattern + ) + + # Map filename (without extension) to template content + templates = { + for rel_path in local.template_files : + trimsuffix(basename(rel_path), ".tmpl") => { + content = file("${path.root}/${var.templates_dir}/${rel_path}") + } + } +} + +resource "grafana_message_template" "templates" { + for_each = local.templates + + name = "${var.template_prefix}${each.key}" + template = each.value.content + disable_provenance = var.disable_provenance +} + diff --git a/grafana/contact-point-gchat/variables.tf b/grafana/contact-point-gchat/variables.tf index 9b9c48c..156bc39 100644 --- a/grafana/contact-point-gchat/variables.tf +++ b/grafana/contact-point-gchat/variables.tf @@ -1,11 +1,32 @@ -# Grafana contact point -variable "gchat-url" { - description = "gchat-webhook url" - type = string - sensitive = true +variable "contact_point_name" { + description = "Name of the Grafana contact point" + type = string } -variable "contact-point-name" { - description = "gchat-contact-point-name" - type = string +variable "gchat_url" { + description = "Google Chat webhook URL" + type = string +} + +variable "templates_dir" { + description = "Path to directory containing template files (.tmpl)" + type = string +} + +variable "file_pattern" { + description = "Pattern to match template files" + type = string + default = "*.tmpl" +} + +variable "disable_provenance" { + description = "Disable provenance for message templates" + type = bool + default = false +} + +variable "template_prefix" { + description = "Optional prefix for template names to avoid collisions" + type = string + default = "" } \ No newline at end of file diff --git a/grafana/datasource/datasource.tf b/grafana/datasource/datasource.tf index 710d31d..b943c87 100644 --- a/grafana/datasource/datasource.tf +++ b/grafana/datasource/datasource.tf @@ -1,11 +1,17 @@ resource "grafana_data_source" "this" { - type = "prometheus" - name = var.datasource_name - url = var.datasource_url + for_each = var.datasources + + name = each.key + type = each.value.type + url = var.datasource_urls[each.value.url_key] + is_default = coalesce(each.value.is_default, false) + basic_auth_enabled = true - basic_auth_username = var.datasource_username + basic_auth_username = var.datasource_users[each.value.user_key] secure_json_data_encoded = jsonencode({ - basicAuthPassword = var.datasource_password + basicAuthPassword = var.datasource_passwords[each.value.pass_key] }) -} \ No newline at end of file + + json_data_encoded = each.value.json_data != null ? jsonencode(each.value.json_data) : null +} diff --git a/grafana/datasource/output.tf b/grafana/datasource/output.tf index f5f6b88..38d026f 100644 --- a/grafana/datasource/output.tf +++ b/grafana/datasource/output.tf @@ -1,3 +1,4 @@ -output "datasource_uid" { - value = grafana_data_source.this.uid +output "datasource_uids" { + description = "UIDs of created Grafana datasources" + value = { for k, v in grafana_data_source.this : k => v.uid } } diff --git a/grafana/datasource/variables.tf b/grafana/datasource/variables.tf index a7a32fc..5602fd8 100644 --- a/grafana/datasource/variables.tf +++ b/grafana/datasource/variables.tf @@ -1,18 +1,35 @@ -# Grafana contact point -variable "datasource_url" { - type = string +# Define datasources (non-sensitive metadata only) +variable "datasources" { + description = <