terraform-provider-grafana icon indicating copy to clipboard operation
terraform-provider-grafana copied to clipboard

Allow grafana_rule_group to have config_json option

Open novy4 opened this issue 2 years ago • 4 comments

Grafana provider has config_json option to import data from JSON file for grafana_dashboard resource:

resource "grafana_dashboard" "metrics" {
  config_json = file("grafana-dashboard.json")
}

Would be nice to have exactly the same config_json option for alert rule_group. At this moment its a bit annoying to process JSON for alerts in TF code.

Grafana API is allowing to import JSON, then why config_json is not present for alerts as for dashboards?

novy4 avatar Apr 04 '23 11:04 novy4

I know, this is not a solution you want, but maybe this will help you?

locals {
  alertrule_files = fileset(path.module, "../alertrules/*.json")
}

resource "grafana_rule_group" "alertrule" {
  provider = grafana.asdf
  org_id = 1
  for_each = { for file in local.alertrule_files : file => jsondecode(file("${path.module}/${file}")) }
  name = replace(each.value.ruleGroup, "/","|") # for now terraform gets 404 response when slash is in name.  See #883 
  folder_uid = each.value.folderUID
  interval_seconds = 60
  rule {
    name = each.value.title
    for = each.value.for
    condition = each.value.condition
    no_data_state = each.value.noDataState
    annotations = each.value.annotations
    exec_err_state = each.value.execErrState
    is_paused = each.value.isPaused
    labels = each.value.labels
    dynamic "data" {
      for_each = each.value.data
      content {
        datasource_uid = data.value.datasourceUid
        ref_id = data.value.refId
        relative_time_range {
          from = data.value.relativeTimeRange.from
          to = data.value.relativeTimeRange.to
        }
        query_type = data.value.queryType
        model = jsonencode(data.value.model)
      }
    }
  }
}

bursztyn-pl avatar Apr 16 '23 23:04 bursztyn-pl

I know, this is not a solution you want, but maybe this will help you?

locals {
  alertrule_files = fileset(path.module, "../alertrules/*.json")
}

resource "grafana_rule_group" "alertrule" {
  provider = grafana.asdf
  org_id = 1
  for_each = { for file in local.alertrule_files : file => jsondecode(file("${path.module}/${file}")) }
  name = replace(each.value.ruleGroup, "/","|") # for now terraform gets 404 response when slash is in name.  See #883 
  folder_uid = each.value.folderUID
  interval_seconds = 60
  rule {
    name = each.value.title
    for = each.value.for
    condition = each.value.condition
    no_data_state = each.value.noDataState
    annotations = each.value.annotations
    exec_err_state = each.value.execErrState
    is_paused = each.value.isPaused
    labels = each.value.labels
    dynamic "data" {
      for_each = each.value.data
      content {
        datasource_uid = data.value.datasourceUid
        ref_id = data.value.refId
        relative_time_range {
          from = data.value.relativeTimeRange.from
          to = data.value.relativeTimeRange.to
        }
        query_type = data.value.queryType
        model = jsonencode(data.value.model)
      }
    }
  }
}

Thank you for the idea ;-)

novy4 avatar Apr 25 '23 10:04 novy4

I also stumbled into this issue. I think a new type of resource grafana_alert_rule could be introduced, that adds an alert rule to a previously created alert group.

I might be looking at this wrong, but current implementation is confusing to me. The API /api/v1/provisioning/alert-rules can be used to import a single alert rule to a specific rule group.

Current implementation creates a single resource for multiple rules if they share an alert group, which is kinda unreadable and hard to maintain if your organization is versioning specific alert rules.

Vimao avatar Nov 08 '23 09:11 Vimao

@Vimao There is also another problem with current approach. If you remove 1st rule, and rest of rules are reordered, API fails, saying that rule already exists. I suppose that it tries to create new 1st rule, which was previously 2nd, and it already exists in DB.

Error: status: 500, body: {"message":"failed to update alert rules: a conflicting alert rule is found: rule title under the same organisation and folder should be unique","traceID":""}

krzysztof-magosa avatar Nov 24 '23 13:11 krzysztof-magosa

@bursztyn-pl Do you have an example of what the alert json file would look like?

ceastman-r7 avatar Feb 08 '25 19:02 ceastman-r7

@novy4 @krzysztof-magosa Do either of you have an example of an alert json file?

ceastman-r7 avatar Feb 11 '25 23:02 ceastman-r7

@ceastman-r7 You can get an alert json file by creating an alert in the UI, and then exporting it, or just grabbing it using the alerting api.

For people that have large amount of alerts they want to maintain independently but still be parts of an alert group in the ui, i recommend just making a json template and use the rest http api provider rather than this resource.

Vimao avatar Feb 12 '25 06:02 Vimao

Is there any update on this? It would let us manage alerts smoothly with https://github.com/grafana/grafana-foundation-sdk

jakubno avatar Jul 07 '25 11:07 jakubno

Example alert in json

{
  "condition": "B",
  "data": [
    {
      "datasourceUid": "grafanacloud-prom",
      "model": {
        "expr": "SuperCriticalAppCpuAvailable < 10",
        "instant": true,
        "range": false,
        "refId": "A"
      },
      "refId": "A",
      "relativeTimeRange": {
        "from": 300,
        "to": 0
      }
    },
    {
      "datasourceUid": "__expr__",
      "model": {
        "conditions": [
          {
            "evaluator": {
              "params": [
                0.9
              ],
              "type": "gt"
            }
          }
        ],
        "datasource": {
          "type": "__expr__",
          "uid": "__expr__"
        },
        "expression": "A",
        "refId": "B",
        "type": "threshold"
      },
      "refId": "B"
    }
  ],
  "execErrState": "Error",
  "folderUID": "abc",
  "for": "0m",
  "noDataState": "NoData",
  "orgID": 0,
  "ruleGroup": "Alerts",
  "title": "A Critical Alert",
  "uid": "efg"
}

jakubno avatar Aug 27 '25 09:08 jakubno

Are you open to contributing? If so, would you suggest creating a new resource grafana_rule_group_json or combining it with the current implemention?

jakubno avatar Aug 27 '25 15:08 jakubno

@julienduchesne any update? Any opinion on

Are you open to contributing? If so, would you suggest creating a new resource grafana_rule_group_json or combining it with the current implemention?

jakubno avatar Sep 10 '25 10:09 jakubno

Hey @jakubno, tks for raising this.

First of all, we're always open for contributions 😄

Note that we do also have the option to export alert rules as HCL in Grafana. Not sure that helps you, but it's worth mentioning.

Regarding which approach to follow if you'd still like to contribute:

I'm not familiar with the config_json implementation for dashboards, but if I were to work on this I'd probably try replicating it first (i.e. using the same resource IIUC). Not sure it makes sense creating a new resource only for json. I'd suggest creating a PR and trying it out; feel free to tag me once you have something so we can move the discussion there 👍

titolins avatar Oct 08 '25 07:10 titolins

Hey @titolins, thanks for your response!

We're currently using https://github.com/grafana/grafana-foundation-sdk to create dashboards in json, which we then pass to Terraform. It's working great and has made dashboard maintenance much easier!

We would like to do the same for alerts. The format we get from the SDK is shared in https://github.com/grafana/terraform-provider-grafana/issues/870#issuecomment-3227400777.

What I would like to do is to have a similar resource as for dashboards https://registry.terraform.io/providers/grafana/grafana/3.25.2/docs/resources/dashboard, where I can pass config_json.

Just to clarify, are you suggesting that we reuse the current setup, add config_json and make it conflicts with current attributes?

jakubno avatar Oct 08 '25 13:10 jakubno

Just to clarify, are you suggesting that we reuse the current setup, add config_json and make it conflicts with current attributes?

How to handle conflicts is an implementation detail, but we'd definitely need to handle it (e.g. if config_json is provided, ignore the rest). My suggestion is more in the sense of looking into how the dashboard resource does it and trying to keep it similar instead of introducing a different logic (which could become confusing for users)

titolins avatar Oct 08 '25 13:10 titolins

Just to clarify, are you suggesting that we reuse the current setup, add config_json and make it conflicts with current attributes?

How to handle conflicts is an implementation detail, but we'd definitely need to handle it (e.g. if config_json is provided, ignore the rest). My suggestion is more in the sense of looking into how the dashboard resource does it and trying to keep it similar instead of introducing a different logic (which could become confusing for users)

Definitely agree. I will try to mimic the handling for the config_json part; hopefully, it won't collide with the current implementation.

jakubno avatar Oct 08 '25 20:10 jakubno