From 9c92329bee8c6f8901eb10fc0f145e5109c3faca Mon Sep 17 00:00:00 2001 From: Pepe Cano <825430+ppcano@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:27:18 +0100 Subject: [PATCH 01/43] Alerting docs: `Provision alerting resources` updates (#82221) * Alert provisioning: initial restructuring * Fix products labels * Restructure `Import and export Grafana Alerting resources` * Change URL to `export-alerting-resources` * Complete `Export alerting resources` * Export alerting resources * Update `configuration files` provisioning * Terraform Provisioning * Change to `Provision/Import/Export` terms and some notes * Replace `config` to `configuration` * Set (menu)Title `Export alerting resources` * Minor change on note about `Export Alerting endpoints` * Fix `doc-validator` issues * Fix grammar * Update docs/sources/alerting/set-up/provision-alerting-resources/terraform-provisioning/index.md Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com> * Update docs/sources/alerting/set-up/provision-alerting-resources/terraform-provisioning/index.md Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com> * Fix numbered lists and `Note:` without admonition * Convert text-based notes (`Note:`) to `admonition` blocks * Replace text-based `Note:` with adminitions * Remove `file-provisioning` grafana-cloud links * Update `Export alerting resources` intro * nitpicky format order --------- Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com> --- docs/sources/alerting/set-up/_index.md | 5 +- .../provision-alerting-resources/_index.md | 143 +- .../export-alerting-resources/index.md | 106 ++ .../file-provisioning/index.md | 279 ++- .../http-api-provisioning/_index.md | 20 + .../terraform-provisioning/index.md | 430 ++--- .../view-provisioned-resources/index.md | 108 -- .../http_api/alerting_provisioning.md | 1524 +--------------- .../shared/alerts/alerting_provisioning.md | 1622 +++++++++++++++++ 9 files changed, 2198 insertions(+), 2039 deletions(-) create mode 100644 docs/sources/alerting/set-up/provision-alerting-resources/export-alerting-resources/index.md create mode 100644 docs/sources/alerting/set-up/provision-alerting-resources/http-api-provisioning/_index.md delete mode 100644 docs/sources/alerting/set-up/provision-alerting-resources/view-provisioned-resources/index.md create mode 100644 docs/sources/shared/alerts/alerting_provisioning.md diff --git a/docs/sources/alerting/set-up/_index.md b/docs/sources/alerting/set-up/_index.md index 761a2be3222..4123fda2935 100644 --- a/docs/sources/alerting/set-up/_index.md +++ b/docs/sources/alerting/set-up/_index.md @@ -54,7 +54,7 @@ Grafana Alerting supports many additional configuration options, from configurin The following topics provide you with advanced configuration options for Grafana Alerting. -- [Provision alert rules using file provisioning][file-provisioning] +- [Provision alert rules using file provisioning](/docs/grafana//alerting/set-up/provision-alerting-resources/file-provisioning) - [Provision alert rules using Terraform][terraform-provisioning] - [Add an external Alertmanager][configure-alertmanager] - [Configure high availability][configure-high-availability] @@ -72,9 +72,6 @@ The following topics provide you with advanced configuration options for Grafana [data-source-management]: "/docs/grafana/ -> /docs/grafana//administration/data-source-management" [data-source-management]: "/docs/grafana-cloud/ -> /docs/grafana//administration/data-source-management" -[file-provisioning]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/file-provisioning" -[file-provisioning]: "/docs/grafana-cloud/ -> /docs/grafana-cloud/alerting-and-irm/alerting/set-up/provision-alerting-resources/file-provisioning" - [terraform-provisioning]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/terraform-provisioning" [terraform-provisioning]: "/docs/grafana-cloud/ -> /docs/grafana-cloud/alerting-and-irm/alerting/set-up/provision-alerting-resources/terraform-provisioning" {{% /docs/reference %}} diff --git a/docs/sources/alerting/set-up/provision-alerting-resources/_index.md b/docs/sources/alerting/set-up/provision-alerting-resources/_index.md index 8e6c588da66..823ae1be82a 100644 --- a/docs/sources/alerting/set-up/provision-alerting-resources/_index.md +++ b/docs/sources/alerting/set-up/provision-alerting-resources/_index.md @@ -2,7 +2,7 @@ aliases: - ../provision-alerting-resources/ canonical: https://grafana.com/docs/grafana/latest/alerting/set-up/provision-alerting-resources/ -description: Import and export alerting resources +description: Provision alerting resources keywords: - grafana - alerting @@ -14,11 +14,11 @@ labels: - cloud - enterprise - oss -title: Import and export Grafana Alerting resources +title: Provision Alerting resources weight: 300 --- -# Import and export Grafana Alerting resources +# Provision Alerting resources Alerting infrastructure is often complex, with many pieces of the pipeline that often live in different places. Scaling this across multiple teams and organizations is an especially challenging task. Importing and exporting (or provisioning) your alerting resources in Grafana Alerting makes this process easier by enabling you to create, manage, and maintain your alerting data in a way that best suits your organization. @@ -26,116 +26,55 @@ You can import alert rules, contact points, notification policies, mute timings, You cannot edit imported alerting resources in the Grafana UI in the same way as alerting resources that were not imported. You can only edit imported contact points, notification policies, templates, and mute timings in the source where they were created. For example, if you manage your alerting resources using files from disk, you cannot edit the data in Terraform or from within Grafana. +## Import alerting resources + +Choose from the options below to import (or provision) your Grafana Alerting resources. + +1. [Use configuration files to provision your alerting resources](/docs/grafana//alerting/set-up/provision-alerting-resources/file-provisioning), such as alert rules and contact points, through files on disk. + + {{< admonition type="note" >}} + File provisioning is not available in Grafana Cloud instances. + {{< /admonition >}} + +1. Use [Terraform to provision alerting resources][alerting_tf_provisioning]. + +1. Use the [Alerting provisioning HTTP API][alerting_http_provisioning] to manage alerting resources. + + {{< admonition type="note" >}} + The JSON output from the majority of Alerting HTTP endpoints isn't compatible for provisioning via configuration files. + Instead, use the [Export Alerting endpoints](/docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources#export-api-endpoints) to return or download the alerting resources in provisioning format. + {{< /admonition >}} + +## Export alerting resources + +You can export both manually created and provisioned alerting resources. For more information, refer to [Export alerting resources][alerting_export]. + To modify imported alert rules, you can use the **Modify export** feature to edit and then export. -Choose from the options below to import your Grafana Alerting resources. +## View provisioned alerting resources -1. Use file provisioning to manage your Grafana Alerting resources, such as alert rules and contact points, through files on disk. +To view your provisioned resources in Grafana, complete the following steps. - {{% admonition type="note" %}} - File provisioning is not available in Grafana Cloud instances. - {{% /admonition %}} +1. Open your Grafana instance. +1. Navigate to Alerting. +1. Click an alerting resource folder, for example, Alert rules. -2. Use the Alerting Provisioning HTTP API. - - For more information on the Alerting Provisioning HTTP API, refer to [Alerting provisioning HTTP API][alerting_provisioning]. - - Here is a ready-to-use template for alert rules: - - #### Alert rules template - -``` -{ - "title": "TEST-API_1", - "ruleGroup": "API", - "folderUID": "FOLDER", - "noDataState": "OK", - "execErrState": "OK", - "for": "5m", - "orgId": 1, - "uid": "", - "condition": "B", - "annotations": { - "summary": "test_api_1" - }, - "labels": { - "API": "test1" - }, - "data": [ - { - "refId": "A", - "queryType": "", - "relativeTimeRange": { - "from": 600, - "to": 0 - }, - "datasourceUid": " XXXXXXXXX-XXXXXXXXX-XXXXXXXXXX", - "model": { - "expr": "up", - "hide": false, - "intervalMs": 1000, - "maxDataPoints": 43200, - "refId": "A" - } - }, - { - "refId": "B", - "queryType": "", - "relativeTimeRange": { - "from": 0, - "to": 0 - }, - "datasourceUid": "-100", - "model": { - "conditions": [ - { - "evaluator": { - "params": [ - 6 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A" - ] - }, - "reducer": { - "params": [], - "type": "last" - }, - "type": "query" - } - ], - "datasource": { - "type": "__expr__", - "uid": "-100" - }, - "hide": false, - "intervalMs": 1000, - "maxDataPoints": 43200, - "refId": "B", - "type": "classic_conditions" - } - } - ] -} -``` - -3. Use [Terraform](https://www.terraform.io/). +Provisioned resources are labeled **Provisioned**, so that it is clear that they were not created manually. **Useful Links:** [Grafana provisioning][provisioning] -[Grafana Alerting provisioning API][alerting_provisioning] - {{% docs/reference %}} -[alerting_provisioning]: "/docs/grafana/ -> /docs/grafana//developers/http_api/alerting_provisioning" -[alerting_provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//developers/http_api/alerting_provisioning" +[alerting_tf_provisioning]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/terraform-provisioning" +[alerting_tf_provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/terraform-provisioning" +[alerting_http_provisioning]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning" +[alerting_http_provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning" +[alerting_export]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources" +[alerting_export]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources" + +[alerting_export_http]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources#export-api-endpoints" +[alerting_export_http]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources#export-api-endpoints" [provisioning]: "/docs/grafana/ -> /docs/grafana//administration/provisioning" [provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//administration/provisioning" diff --git a/docs/sources/alerting/set-up/provision-alerting-resources/export-alerting-resources/index.md b/docs/sources/alerting/set-up/provision-alerting-resources/export-alerting-resources/index.md new file mode 100644 index 00000000000..2bfc1500c1b --- /dev/null +++ b/docs/sources/alerting/set-up/provision-alerting-resources/export-alerting-resources/index.md @@ -0,0 +1,106 @@ +--- +aliases: + - ../../provision-alerting-resources/view-provisioned-resources/ + - ./view-provisioned-resources/ +canonical: https://grafana.com/docs/grafana/latest/alerting/set-up/provision-alerting-resources/export-alerting-resources/ +description: Export alerting resources in Grafana +keywords: + - grafana + - alerting + - alerting resources + - provisioning +labels: + products: + - cloud + - enterprise + - oss +title: Export alerting resources +weight: 300 +--- + +# Export alerting resources + +Export your alerting resources, such as alert rules, contact points, and notification policies for provisioning, automatically importing single folders and single groups. + +The export options listed below enable you to download resources in YAML, JSON, or Terraform format, facilitating their provisioning through [configuration files](/docs/grafana//alerting/set-up/provision-alerting-resources/file-provisioning) or [Terraform][alerting_tf_provisioning]. + +## Export alert rules + +To export alert rules from the Grafana UI, complete the following steps. + +1. Click **Alerts & IRM** -> **Alert rules**. +1. To export all Grafana-managed rules, click **Export rules**. +1. To export a folder, change the **View as** to **List**. +1. Select the folder you want to export and click the **Export rules folder** icon. +1. To export a group, change the **View as** to **Grouped**. +1. Find the group you want to export and click the **Export rule group** icon. +1. Choose the format to export in. + + The exported rule data appears in different formats - YAML, JSON, Terraform. + +1. Click **Copy Code** or **Download**. + + a. Choose **Copy Code** to go to an existing file and paste in the code. + + b. Choose **Download** to download a file with the exported data. + +## Modify and export alert rules without saving changes + +Use the **Modify export** mode to edit and export an alert rule without updating it. + +{{% admonition type="note" %}} This feature is for Grafana-managed alert rules only. It is available to Admin, Viewer, and Editor roles. {{% /admonition %}} + +To export a modified alert rule without saving the modifications, complete the following steps from the Grafana UI. + +1. Click **Alerts & IRM** -> **Alert rules**. +1. Locate the alert rule you want to edit and click **More** -> **Modify Export** to open the Alert Rule form. +1. From the Alert Rule form, edit the fields you want to change. Changes made are not applied to the alert rule. +1. Click **Export**. +1. Choose the format to export in. + + The exported rule data appears in different formats - YAML, JSON, Terraform. + +1. Click **Copy Code** or **Download**. + + a. Choose **Copy Code** to go to an existing file and paste in the code. + + b. Choose **Download** to download a file with the exported data. + +## Export API endpoints + +You can also use the **Alerting provisioning HTTP API** to export alerting resources in YAML or JSON formats for provisioning. + +Note that most Alerting endpoints return a JSON format that is not compatible for provisioning via configuration files, except the ones listed below. + +| Method | URI | Summary | +| ------ | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| GET | /api/v1/provisioning/alert-rules/:uid/export | [Export an alert rule in provisioning file format.][export_rule] | +| GET | /api/v1/provisioning/folder/:folderUid/rule-groups/:group/export | [Export an alert rule group in provisioning file format.][export_rule_group] | +| GET | /api/v1/provisioning/alert-rules/export | [Export all alert rules in provisioning file format.][export_rules] | +| GET | /api/v1/provisioning/contact-points/export | [Export all contact points in provisioning file format.][export_contacts] | +| GET | /api/v1/provisioning/policies/export | [Export the notification policy tree in provisioning file format.][export_notifications] | + +These endpoints accept a `download` parameter to download a file containing the exported resources. + +{{% docs/reference %}} +[alerting_tf_provisioning]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/terraform-provisioning" +[alerting_tf_provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/terraform-provisioning" + +[alerting_http_provisioning]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning" +[alerting_http_provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning" + +[export_rule]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-alert-rule-exportspan-export-an-alert-rule-in-provisioning-file-format-_routegetalertruleexport_" +[export_rule]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-alert-rule-exportspan-export-an-alert-rule-in-provisioning-file-format-_routegetalertruleexport_" + +[export_rule_group]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-alert-rule-group-exportspan-export-an-alert-rule-group-in-provisioning-file-format-_routegetalertrulegroupexport_" +[export_rule_group]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-alert-rule-group-exportspan-export-an-alert-rule-group-in-provisioning-file-format-_routegetalertrulegroupexport_" + +[export_rules]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-alert-rules-exportspan-export-all-alert-rules-in-provisioning-file-format-_routegetalertrulesexport_" +[export_rules]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-alert-rules-exportspan-export-all-alert-rules-in-provisioning-file-format-_routegetalertrulesexport_" + +[export_contacts]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-contactpoints-exportspan-export-all-contact-points-in-provisioning-file-format-_routegetcontactpointsexport_" +[export_contacts]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-contactpoints-exportspan-export-all-contact-points-in-provisioning-file-format-_routegetcontactpointsexport_" + +[export_notifications]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-policy-tree-exportspan-export-the-notification-policy-tree-in-provisioning-file-format-_routegetpolicytreeexport_" +[export_notifications]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning/#span-idroute-get-policy-tree-exportspan-export-the-notification-policy-tree-in-provisioning-file-format-_routegetpolicytreeexport_" +{{% /docs/reference %}} diff --git a/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md b/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md index b99e6a70f22..63018a906ad 100644 --- a/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md +++ b/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md @@ -11,14 +11,14 @@ keywords: - provisioning labels: products: - - cloud - enterprise - oss -title: Use file provisioning to manage alerting resources +menuTitle: Use configuration files to provision +title: Use configuration files to provision alerting resources weight: 100 --- -## Use file provisioning to manage alerting resources +# Use configuration files to provision alerting resources Manage your alerting resources using files from disk. When you start Grafana, the data from these files is created in your Grafana system. Grafana adds any new resources you created, updates any that you changed, and deletes old ones. @@ -26,26 +26,28 @@ Arrange your files in a directory in a way that best suits your use case. For ex Details on how to set up the files and which fields are required for each object are listed below depending on which resource you are provisioning. -**Note:** +For a complete guide about how Grafana provisions resources, refer to the [Provision Grafana][provisioning] documentation. -Importing takes place during the initial set up of your Grafana system, but you can re-run it at any time using the [Grafana Admin API][reload-provisioning-configurations]. +{{< admonition type="note" >}} -### Import alert rules +- You cannot edit provisioned resources from files in Grafana. You can only change the resource properties by changing the provisioning file and restarting Grafana or carrying out a hot reload. This prevents changes being made to the resource that would be overwritten if a file is provisioned again or a hot reload is carried out. + +- Importing takes place during the initial set up of your Grafana system, but you can re-run it at any time using the [Grafana Admin API](/docs/grafana//developers/http_api/admin#reload-provisioning-configurations). + +- Importing an existing alerting resource results in a conflict. First, when present, remove the resources you plan to import. + {{< /admonition >}} + +## Import alert rules Create or delete alert rules in your Grafana instance(s). 1. Create alert rules in Grafana. -1. Use the [Alerting provisioning API][alerting_provisioning] export endpoints to download a provisioning file for your alert rules. -1. Copy the contents into a YAML or JSON configuration file in the default provisioning directory or in your configured directory. +1. [Export][alerting_export] and download a provisioning file for your alert rules. +1. Copy the contents into a YAML or JSON configuration file in the `provisioning/alerting` directory. Example configuration files can be found below. -1. Ensure that your files are in the right directory on the node running the Grafana server, so that they deploy alongside your Grafana instance(s). -1. Delete the alert rules in Grafana that are going to be imported. - - **Note:** - - If you do not delete the alert rule, it will clash with the imported alert rule once uploaded. +1. Add the file(s) to your GitOps workflow, so that they deploy alongside your Grafana instance(s). Here is an example of a configuration file for creating alert rules. @@ -134,17 +136,17 @@ deleteRules: uid: my_id_1 ``` -### Import contact points +## Import contact points Create or delete contact points in your Grafana instance(s). 1. Create a contact point in Grafana. -1. Use the [Alerting provisioning API][alerting_provisioning] export endpoints to download a provisioning file for your contact point. -1. Copy the contents into a YAML or JSON configuration file in the default provisioning directory or in your configured directory. +1. [Export][alerting_export] and download a provisioning file for your contact point. +1. Copy the contents into a YAML or JSON configuration file in the `provisioning/alerting` directory. Example configuration files can be found below. -1. Ensure that your files are in the right directory on the node running the Grafana server, so that they deploy alongside your Grafana instance(s). +1. Add the file(s) to your GitOps workflow, so that they deploy alongside your Grafana instance(s). Here is an example of a configuration file for creating contact points. @@ -184,12 +186,14 @@ deleteContactPoints: uid: first_uid ``` -#### Settings +### Settings Here are some examples of settings you can use for the different contact point integrations. -##### Alertmanager +{{< collapse title="Alertmanager" >}} + +#### Alertmanager ```yaml type: prometheus-alertmanager @@ -202,7 +206,11 @@ settings: basicAuthPassword: abc123 ``` -##### DingDing +{{< /collapse >}} + +{{< collapse title="DingDing" >}} + +#### DingDing ```yaml type: dingding @@ -216,7 +224,11 @@ settings: {{ template "default.message" . }} ``` -##### Discord +{{< /collapse >}} + +{{< collapse title="Discord" >}} + +#### Discord ```yaml type: discord @@ -232,7 +244,11 @@ settings: {{ template "default.message" . }} ``` -##### E-Mail +{{< /collapse >}} + +{{< collapse title="E-Mail" >}} + +#### E-Mail ```yaml type: email @@ -248,7 +264,11 @@ settings: {{ template "default.title" . }} ``` -##### Google Chat +{{< /collapse >}} + +{{< collapse title="Google Chat" >}} + +#### Google Chat ```yaml type: googlechat @@ -260,7 +280,11 @@ settings: {{ template "default.message" . }} ``` -##### Kafka +{{< /collapse >}} + +{{< collapse title="Kafka" >}} + +#### Kafka ```yaml type: kafka @@ -271,7 +295,11 @@ settings: kafkaTopic: topic1 ``` -##### LINE +{{< /collapse >}} + +{{< collapse title="LINE" >}} + +#### LINE ```yaml type: line @@ -280,7 +308,11 @@ settings: token: xxx ``` -##### Microsoft Teams +{{< /collapse >}} + +{{< collapse title="Microsoft Teams" >}} + +#### Microsoft Teams ```yaml type: teams @@ -297,7 +329,11 @@ settings: {{ template "default.message" . }} ``` -##### OpsGenie +{{< /collapse >}} + +{{< collapse title="OpsGenie" >}} + +#### OpsGenie ```yaml type: opsgenie @@ -319,7 +355,11 @@ settings: sendTagsAs: both ``` -##### PagerDuty +{{< /collapse >}} + +{{< collapse title="PagerDuty" >}} + +#### PagerDuty ```yaml type: pagerduty @@ -339,7 +379,11 @@ settings: {{ template "default.message" . }} ``` -##### Pushover +{{< /collapse >}} + +{{< collapse title="Pushover" >}} + +#### Pushover ```yaml type: pushover @@ -367,7 +411,11 @@ settings: {{ template "default.message" . }} ``` -##### Slack +{{< /collapse >}} + +{{< collapse title="Slack" >}} + +#### Slack ```yaml type: slack @@ -399,7 +447,11 @@ settings: {{ template "slack.default.text" . }} ``` -##### Sensu Go +{{< /collapse >}} + +{{< collapse title="Sensu Go" >}} + +#### Sensu Go ```yaml type: sensugo @@ -421,7 +473,11 @@ settings: {{ template "default.message" . }} ``` -##### Telegram +{{< /collapse >}} + +{{< collapse title="Telegram" >}} + +#### Telegram ```yaml type: telegram @@ -435,7 +491,11 @@ settings: {{ template "default.message" . }} ``` -##### Threema Gateway +{{< /collapse >}} + +{{< collapse title="Threema Gateway" >}} + +#### Threema Gateway ```yaml type: threema @@ -448,7 +508,11 @@ settings: recipient_id: A9R4KL4S ``` -##### VictorOps +{{< /collapse >}} + +{{< collapse title="VictorOps" >}} + +#### VictorOps ```yaml type: victorops @@ -459,7 +523,11 @@ settings: messageType: CRITICAL ``` -##### Webhook +{{< /collapse >}} + +{{< collapse title="Webhook" >}} + +#### Webhook ```yaml type: webhook @@ -480,7 +548,11 @@ settings: maxAlerts: '10' ``` -##### WeCom +{{< /collapse >}} + +{{< collapse title="WeCom" >}} + +#### WeCom ```yaml type: wecom @@ -495,17 +567,27 @@ settings: {{ template "default.title" . }} ``` -### Import notification policies +{{< /collapse >}} + +## Import notification policies Create or reset the notification policy tree in your Grafana instance(s). +In Grafana, the entire notification policy tree is considered a single, large resource. Add new specific policies as sub-policies under the root policy. Since specific policies may depend on each other, you cannot provision subsets of the policy tree; the entire tree must be defined in a single place. + +{{% admonition type="warning" %}} + +Since the policy tree is a single resource, provisioning it will overwrite a policy tree created through any other means. + +{{< /admonition >}} + 1. Create a notification policy in Grafana. -1. Use the [Alerting provisioning API][alerting_provisioning] export endpoints to download a provisioning file for your notification policy. -1. Copy the contents into a YAML or JSON configuration file in the default provisioning directory or in your configured directory. +1. [Export][alerting_export] and download a provisioning file for your notification policy. +1. Copy the contents into a YAML or JSON configuration file in the `provisioning/alerting` directory. Example configuration files can be found below. -1. Ensure that your files are in the right directory on the node running the Grafana server, so that they deploy alongside your Grafana instance(s). +1. Add the file(s) to your GitOps workflow, so that they deploy alongside your Grafana instance(s). Here is an example of a configuration file for creating notification policies. @@ -581,13 +663,7 @@ resetPolicies: - 1 ``` -**Note:** - -In Grafana, the entire notification policy tree is considered a single, large resource. Add new specific policies as sub-policies under the root policy. Since specific policies may depend on each other, you cannot provision subsets of the policy tree; the entire tree must be defined in a single place. - -Since the policy tree is a single resource, applying it will overwrite a policy tree created through any other means. - -### Import templates +## Import templates Create or delete templates in your Grafana instance(s). @@ -595,7 +671,7 @@ Create or delete templates in your Grafana instance(s). Example configuration files can be found below. -2. Add the file(s) to your GitOps workflow, so that they deploy alongside your Grafana instance(s). +1. Add the file(s) to your GitOps workflow, so that they deploy alongside your Grafana instance(s). Here is an example of a configuration file for creating templates. @@ -627,7 +703,7 @@ deleteTemplates: name: my_first_template ``` -### Import mute timings +## Import mute timings Create or delete mute timings in your Grafana instance(s). @@ -676,65 +752,68 @@ deleteMuteTimes: name: mti_1 ``` -### File provisioning using Kubernetes +## File provisioning using Kubernetes If you are a Kubernetes user, you can leverage file provisioning using Kubernetes configuration maps. 1. Create one or more configuration maps as follows. -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: grafana-alerting -data: - provisioning.yaml: | - templates: - - name: my_first_template - template: the content for my template -``` + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: grafana-alerting + data: + provisioning.yaml: | + templates: + - name: my_first_template + template: the content for my template + ``` -2. Add the file(s) to your GitOps workflow, so that they deploy alongside your Grafana instance(s). +1. Add the file(s) to your GitOps workflow, so that they deploy alongside your Grafana instance(s). -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: grafana -spec: - replicas: 1 - selector: - matchLabels: - app: grafana - template: - metadata: - name: grafana - labels: - app: grafana - spec: - containers: - - name: grafana - image: grafana/grafana:latest - ports: - - name: grafana - containerPort: 3000 - volumeMounts: - - mountPath: /etc/grafana/provisioning/alerting - name: grafana-alerting - readOnly: false - volumes: - - name: grafana-alerting - configMap: - defaultMode: 420 - name: grafana-alerting -``` + ```yaml + apiVersion: apps/v1 + kind: Deployment + metadata: + name: grafana + spec: + replicas: 1 + selector: + matchLabels: + app: grafana + template: + metadata: + name: grafana + labels: + app: grafana + spec: + containers: + - name: grafana + image: grafana/grafana:latest + ports: + - name: grafana + containerPort: 3000 + volumeMounts: + - mountPath: /etc/grafana/provisioning/alerting + name: grafana-alerting + readOnly: false + volumes: + - name: grafana-alerting + configMap: + defaultMode: 420 + name: grafana-alerting + ``` This eliminates the need for a persistent database to use Grafana Alerting in Kubernetes; all your provisioned resources appear after each restart or re-deployment. Grafana still requires a database for normal operation, you do not need to persist the contents of the database between restarts if all objects are provisioned using files. -{{% docs/reference %}} -[alerting_provisioning]: "/docs/grafana/ -> /docs/grafana//developers/http_api/alerting_provisioning" -[alerting_provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//developers/http_api/alerting_provisioning" +**Useful Links:** -[reload-provisioning-configurations]: "/docs/grafana/ -> /docs/grafana//developers/http_api/admin#reload-provisioning-configurations" -[reload-provisioning-configurations]: "/docs/grafana-cloud/ -> /docs/grafana//developers/http_api/admin#reload-provisioning-configurations" +[Grafana provisioning][provisioning] + +{{% docs/reference %}} +[alerting_export]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources" +[alerting_export]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources" +[provisioning]: "/docs/grafana/ -> /docs/grafana//administration/provisioning" +[provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//administration/provisioning" {{% /docs/reference %}} diff --git a/docs/sources/alerting/set-up/provision-alerting-resources/http-api-provisioning/_index.md b/docs/sources/alerting/set-up/provision-alerting-resources/http-api-provisioning/_index.md new file mode 100644 index 00000000000..4c1f4606571 --- /dev/null +++ b/docs/sources/alerting/set-up/provision-alerting-resources/http-api-provisioning/_index.md @@ -0,0 +1,20 @@ +--- +canonical: https://grafana.com/docs/grafana/latest/developers/http_api/alerting_provisioning/ +description: Create and manage alerting resources using the HTTP API +keywords: + - grafana + - alerting + - alerting resources + - provisioning +labels: + products: + - cloud + - enterprise + - oss +title: Use the HTTP API to manage alerting resources +weight: 400 +--- + +# Use the HTTP API to manage alerting resources + +{{< docs/shared lookup="alerts/alerting_provisioning.md" source="grafana" version="latest" >}} diff --git a/docs/sources/alerting/set-up/provision-alerting-resources/terraform-provisioning/index.md b/docs/sources/alerting/set-up/provision-alerting-resources/terraform-provisioning/index.md index 0ad04166a99..5050d2868f9 100644 --- a/docs/sources/alerting/set-up/provision-alerting-resources/terraform-provisioning/index.md +++ b/docs/sources/alerting/set-up/provision-alerting-resources/terraform-provisioning/index.md @@ -11,41 +11,46 @@ keywords: - Terraform labels: products: + - cloud - enterprise - oss -title: Use Terraform to manage alerting resources +menuTitle: Use Terraform to provision +title: Use Terraform to provision alerting resources weight: 200 --- -# Use Terraform to manage alerting resources +# Use Terraform to provision alerting resources Use Terraform’s Grafana Provider to manage your alerting resources and provision them into your Grafana system. Terraform provider support for Grafana Alerting makes it easy to create, manage, and maintain your entire Grafana Alerting stack as code. -For more information on managing your alerting resources using Terraform, refer to the [Grafana Provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs) documentation. +Refer to [Grafana Provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs) documentation for more examples and information on Terraform Alerting schemas. Complete the following tasks to create and manage your alerting resources using Terraform. 1. Create an API key for provisioning. 1. Configure the Terraform provider. -1. Define your alerting resources in Terraform. +1. Define your alerting resources in Terraform. [Export alerting resources][alerting_export] in Terraform format, or implement the [Terraform Alerting schemas](https://registry.terraform.io/providers/grafana/grafana/latest/docs). + 1. Run `terraform apply` to provision your alerting resources. -## Before you begin +{{< admonition type="note" >}} -- Ensure you have the grafana/grafana [Terraform provider](https://registry.terraform.io/providers/grafana/grafana/1.28.0) 1.27.0 or higher. +- By default, you cannot edit resources provisioned from Terraform from the UI. This ensures that your alerting stack always stays in sync with your code. To change the default behaviour, refer to [Edit provisioned resources in the Grafana UI](#edit-provisioned-resources-in-the-grafana-ui). -- Ensure you are using Grafana 9.1 or higher. +- Before you begin, ensure you have the [Grafana Terraform Provider](https://registry.terraform.io/providers/grafana/grafana/) 1.27.0 or higher, and are using Grafana 9.1 or higher. + +{{< /admonition >}} ## Create an API key for provisioning -You can [create a normal Grafana API key][api-keys] to authenticate Terraform with Grafana. Most existing tooling using API keys should automatically work with the new Grafana Alerting support. +You can create a [service account token][service-accounts] to authenticate Terraform with Grafana. Most existing tooling using API keys should automatically work with the new Grafana Alerting support. -There are also dedicated RBAC roles for alerting provisioning. This lets you easily authenticate as a [service account][service-accounts] with the minimum permissions needed to provision your Alerting infrastructure. +There are also dedicated RBAC roles for alerting provisioning. This lets you easily authenticate as a service account with the minimum permissions needed to provision your Alerting infrastructure. To create an API key for provisioning, complete the following steps. -1. Create a new service account for your CI pipeline. -1. Assign the role “Access the alert rules Provisioning API.” +1. Create a new service account. +1. Assign the role or permission to access the [Alerting provisioning API][alerting_http_provisioning]. 1. Create a new service account token. 1. Name and save the token for use in Terraform. @@ -73,70 +78,68 @@ provider "grafana" { } ``` -## Provision contact points and templates +## Import contact points and templates -Contact points connect an alerting stack to the outside world. They tell Grafana how to connect to your external systems and where to deliver notifications. There are over fifteen different [integrations](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/contact_point#optional) to choose from. +Contact points connect an alerting stack to the outside world. They tell Grafana how to connect to your external systems and where to deliver notifications. -To provision contact points and templates, complete the following steps. +To provision contact points and templates, refer to the [grafana_contact_point schema](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/contact_point) and [grafana_message_template schema](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/message_template), and complete the following steps. -1. Copy this code block into a .tf file on your local machine. +1. Copy this code block into a `.tf` file on your local machine. -This example creates a contact point that sends alert notifications to Slack. + This example creates a contact point that sends alert notifications to Slack. -```HCL -resource "grafana_contact_point" "my_slack_contact_point" { - name = "Send to My Slack Channel" + ```HCL + resource "grafana_contact_point" "my_slack_contact_point" { + name = "Send to My Slack Channel" - slack { - url = - text = < + text = <}} -```HCL -resource "grafana_notification_policy" "my_policy" { - group_by = ["alertname"] - contact_point = grafana_contact_point.my_slack_contact_point.name +1. Copy this code block into a `.tf` file on your local machine. - group_wait = "45s" - group_interval = "6m" - repeat_interval = "3h" + In this example, the alerts are grouped by `alertname`, which means that any notifications coming from alerts which share the same name, are grouped into the same Slack message. You can provide any set of label keys here, or you can use the special label `"..."` to route by all label keys, sending each alert in a separate notification. - policy { - matcher { - label = "a" - match = "=" - value = "b" - } - group_by = ["..."] - contact_point = grafana_contact_point.a_different_contact_point.name - mute_timings = [grafana_mute_timing.my_mute_timing.name] + If you want to route specific notifications differently, you can add sub-policies. Sub-policies allow you to apply routing to different alerts based on label matching. In this example, we apply a mute timing to all alerts with the label a=b. - policy { - matcher { - label = "sublabel" - match = "=" - value = "subvalue" - } - contact_point = grafana_contact_point.a_third_contact_point.name - group_by = ["..."] - } - } -} -``` + ```HCL + resource "grafana_notification_policy" "my_policy" { + group_by = ["alertname"] + contact_point = grafana_contact_point.my_slack_contact_point.name -2. In the mute_timings field, link a mute timing to your notification policy. + group_wait = "45s" + group_interval = "6m" + repeat_interval = "3h" -3. Run the command ‘terraform apply’. + policy { + matcher { + label = "a" + match = "=" + value = "b" + } + group_by = ["..."] + contact_point = grafana_contact_point.a_different_contact_point.name + mute_timings = [grafana_mute_timing.my_mute_timing.name] -4. Go to the Grafana UI and check the details of your notification policy. + policy { + matcher { + label = "sublabel" + match = "=" + value = "subvalue" + } + contact_point = grafana_contact_point.a_third_contact_point.name + group_by = ["..."] + } + } + } + ``` -**Note:** +1. In the mute_timings field, link a mute timing to your notification policy. -Since the policy tree is a single resource, applying it will overwrite a policy tree created through any other means. +1. Run the command `terraform apply`. -By default, you cannot edit resources provisioned from Terraform from the UI. This ensures that your alerting stack always stays in sync with your code. +1. Go to the Grafana UI and check the details of your notification policy. -5. Click **Test** to verify that the notification point is working correctly. +1. Click **Test** to verify that the notification point is working correctly. -## Provision mute timings +## Import mute timings Mute timings provide the ability to mute alert notifications for defined time periods. -To provision mute timings, complete the following steps. +To provision mute timings, refer to the [grafana_mute_timing schema](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/mute_timing), and complete the following steps. -1. Copy this code block into a .tf file on your local machine. +1. Copy this code block into a `.tf` file on your local machine. -In this example, alert notifications are muted on weekends. + In this example, alert notifications are muted on weekends. -```HCL -resource "grafana_mute_timing" "my_mute_timing" { - name = "My Mute Timing" + ```HCL + resource "grafana_mute_timing" "my_mute_timing" { + name = "My Mute Timing" - intervals { - times { - start = "04:56" - end = "14:17" - } - weekdays = ["saturday", "sunday", "tuesday:thursday"] - months = ["january:march", "12"] - years = ["2025:2027"] - } -} -``` + intervals { + times { + start = "04:56" + end = "14:17" + } + weekdays = ["saturday", "sunday", "tuesday:thursday"] + months = ["january:march", "12"] + years = ["2025:2027"] + } + } + ``` -2. Run the command ‘terraform apply’. -3. Go to the Grafana UI and check the details of your mute timing. -4. Reference your newly created mute timing in a notification policy using the `mute_timings` field. +1. Run the command `terraform apply`. +1. Go to the Grafana UI and check the details of your mute timing. +1. Reference your newly created mute timing in a notification policy using the `mute_timings` field. This will apply your mute timing to some or all of your notifications. -**Note:** +1. Click **Test** to verify that the mute timing is working correctly. -By default, you cannot edit resources provisioned from Terraform from the UI. This ensures that your alerting stack always stays in sync with your code. - -5. Click **Test** to verify that the mute timing is working correctly. - -## Provision alert rules +## Import alert rules [Alert rules][alerting-rules] enable you to alert against any Grafana data source. This can be a data source that you already have configured, or you can [define your data sources in Terraform](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/data_source) alongside your alert rules. -To provision alert rules, complete the following steps. +To provision alert rules, refer to the [grafana_rule_group schema](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/rule_group), and complete the following steps. 1. Create a data source to query and a folder to store your rules in. -In this example, the [TestData][testdata] data source is used. + In this example, the [TestData][testdata] data source is used. -Alerts can be defined against any backend datasource in Grafana. + Alerts can be defined against any backend datasource in Grafana. -```HCL -resource "grafana_data_source" "testdata_datasource" { - name = "TestData" - type = "testdata" -} + ```HCL + resource "grafana_data_source" "testdata_datasource" { + name = "TestData" + type = "testdata" + } -resource "grafana_folder" "rule_folder" { - title = "My Rule Folder" -} -``` + resource "grafana_folder" "rule_folder" { + title = "My Rule Folder" + } + ``` -2. Define an alert rule. +1. Define an alert rule. -For more information on alert rules, refer to [how to create Grafana-managed alerts](/blog/2022/08/01/grafana-alerting-video-how-to-create-alerts-in-grafana-9/). + For more information on alert rules, refer to [how to create Grafana-managed alerts](/blog/2022/08/01/grafana-alerting-video-how-to-create-alerts-in-grafana-9/). -3. Create a rule group containing one or more rules. +1. Create a rule group containing one or more rules. -In this example, the `grafana_rule_group` resource group is used. + In this example, the `grafana_rule_group` resource group is used. -```HCL -resource "grafana_rule_group" "my_rule_group" { - name = "My Alert Rules" - folder_uid = grafana_folder.rule_folder.uid - interval_seconds = 60 - org_id = 1 + ```HCL + resource "grafana_rule_group" "my_rule_group" { + name = "My Alert Rules" + folder_uid = grafana_folder.rule_folder.uid + interval_seconds = 60 + org_id = 1 - rule { - name = "My Random Walk Alert" - condition = "C" - for = "0s" + rule { + name = "My Random Walk Alert" + condition = "C" + for = "0s" - // Query the datasource. - data { - ref_id = "A" - relative_time_range { - from = 600 - to = 0 - } - datasource_uid = grafana_data_source.testdata_datasource.uid - // `model` is a JSON blob that sends datasource-specific data. - // It's different for every datasource. The alert's query is defined here. - model = jsonencode({ - intervalMs = 1000 - maxDataPoints = 43200 - refId = "A" - }) - } + // Query the datasource. + data { + ref_id = "A" + relative_time_range { + from = 600 + to = 0 + } + datasource_uid = grafana_data_source.testdata_datasource.uid + // `model` is a JSON blob that sends datasource-specific data. + // It's different for every datasource. The alert's query is defined here. + model = jsonencode({ + intervalMs = 1000 + maxDataPoints = 43200 + refId = "A" + }) + } - // The query was configured to obtain data from the last 60 seconds. Let's alert on the average value of that series using a Reduce stage. - data { - datasource_uid = "__expr__" - // You can also create a rule in the UI, then GET that rule to obtain the JSON. - // This can be helpful when using more complex reduce expressions. - model = < /docs/grafana//alerting/alerting-rules" [alerting-rules]: "/docs/grafana-cloud/ -> /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules" -[api-keys]: "/docs/grafana/ -> /docs/grafana//administration/api-keys" -[api-keys]: "/docs/grafana-cloud/ -> /docs/grafana//administration/api-keys" +[alerting_export]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources" +[alerting_export]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/export-alerting-resources" + +[alerting_http_provisioning]: "/docs/grafana/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning" +[alerting_http_provisioning]: "/docs/grafana-cloud/ -> /docs/grafana//alerting/set-up/provision-alerting-resources/http-api-provisioning" [service-accounts]: "/docs/grafana/ -> /docs/grafana//administration/service-accounts" [service-accounts]: "/docs/grafana-cloud/ -> /docs/grafana//administration/service-accounts" diff --git a/docs/sources/alerting/set-up/provision-alerting-resources/view-provisioned-resources/index.md b/docs/sources/alerting/set-up/provision-alerting-resources/view-provisioned-resources/index.md deleted file mode 100644 index 5b473a7776d..00000000000 --- a/docs/sources/alerting/set-up/provision-alerting-resources/view-provisioned-resources/index.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -aliases: - - ../../provision-alerting-resources/view-provisioned-resources/ -canonical: https://grafana.com/docs/grafana/latest/alerting/set-up/provision-alerting-resources/view-provisioned-resources/ -description: Manage provisioned alerting resources in Grafana -keywords: - - grafana - - alerting - - alerting resources - - provisioning -labels: - products: - - cloud - - enterprise - - oss -menuTitle: Manage provisioned alerting resources -title: Manage provisioned alerting resources -weight: 300 ---- - -# Manage provisioned alerting resources - -Verify that your alerting resources were created in Grafana, as well as edit or export your provisioned alerting resources. - -## View provisioned alerting resoureces - -To view your provisioned resources in Grafana, complete the following steps. - -1. Open your Grafana instance. -1. Navigate to Alerting. -1. Click an alerting resource folder, for example, Alert rules. - -Provisioned resources are labeled **Provisioned**, so that it is clear that they were not created manually. - -## Export provisioned alerting resources - -Export your alerting resources, such as alert rules, contact points, and notification policies in JSON, YAML, or Terraform format. You can export all Grafana-managed alert rules, single folders, and single groups. - -To export provisioned alerting resources from the Grafana UI, complete the following steps. - -1. Click **Alerts & IRM** -> **Alert rules**. -1. To export all Grafana-managed rules, click **Export rules**. -1. To export a folder, change the **View as** to **List**. -1. Select the folder you want to export and click the **Export rules folder** icon. -1. To export a group, change the **View as** to **Grouped**. -1. Find the group you want to export and click the **Export rule group** icon. -1. Choose the format to export in. - - Note that formats JSON and YAML are suitable only for file provisioning. To get rule definition in provisioning API format, use the provisioning GET API. - -1. Click **Copy Code** or **Download**. -1. Choose **Copy Code** to go to an existing file and paste in the code. -1. Choose **Download** to download a file with the exported data. - -## Edit provisioned alert rules - -Use the **Modify export** mode for alert rules to edit provisioned alert rules and export a modified version. - -{{% admonition type="note" %}} This feature is for Grafana-managed alert rules only. It is available to Admin, Viewer, and Editor roles. {{% /admonition %}} - -To edit provisioned alerting alert rules from the Grafana UI, complete the following steps. - -1. Click **Alerts & IRM** -> **Alert rules**. -1. Locate the alert rule you want to edit and click **More** -> **Modify Export** to open the Alert Rule form. -1. From the Alert Rule form, edit the fields you want to change. -1. Click **Export** to export all alert rules within the group. - - You can only export groups of rules; not single rules. - The exported rule data appears in different formats - HTML, JSON, Terraform. - -1. Choose the format to export in. -1. Click **Copy Code** or **Download**. - - a. Choose **Copy Code** to go to an existing file and paste in the code. - - b. Choose **Download** to download a file with the exported data. - -## Edit API-provisioned alerting resources - -To enable editing of API-provisioned resources in the Grafana UI, add the `X-Disable-Provenance` header to the following requests in the API: - -- `POST /api/v1/provisioning/alert-rules` -- `PUT /api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}` (calling this endpoint will change provenance for all alert rules within the alert group) -- `POST /api/v1/provisioning/contact-points` -- `POST /api/v1/provisioning/mute-timings` -- `PUT /api/v1/provisioning/policies` -- `PUT /api/v1/provisioning/templates/{name}` - -To reset the notification policy tree to the default and unlock it for editing in the Grafana UI, use the `DELETE /api/v1/provisioning/policies` endpoint. - -In Terraform, you can use the `disable_provenance` attribute on alerting resources: - -``` -provider "grafana" { - url = "http://grafana.example.com/" - auth = var.grafana_auth -} - -resource "grafana_mute_timing" "mute_all" { - name = "mute all" - disable_provenance = true - intervals {} -} -``` - -**Note:** - -You cannot edit provisioned resources from files in Grafana. You can only change the resource properties by changing the provisioning file and restarting Grafana or carrying out a hot reload. This prevents changes being made to the resource that would be overwritten if a file is provisioned again or a hot reload is carried out. diff --git a/docs/sources/developers/http_api/alerting_provisioning.md b/docs/sources/developers/http_api/alerting_provisioning.md index 7643fabd65a..0f9cfe3225a 100644 --- a/docs/sources/developers/http_api/alerting_provisioning.md +++ b/docs/sources/developers/http_api/alerting_provisioning.md @@ -12,6 +12,7 @@ keywords: - alerts labels: products: + - cloud - enterprise - oss title: 'Alerting Provisioning HTTP API ' @@ -19,1525 +20,4 @@ title: 'Alerting Provisioning HTTP API ' # Alerting provisioning HTTP API -The Alerting provisioning API can be used to create, modify, and delete resources relevant to [Grafana Managed alerts]({{< relref "/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule" >}}). And is the one used by our [Grafana Terraform provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs). - -For managing resources related to [data source-managed alerts]({{< relref "/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule" >}}) including Recording Rules, you can use [Mimir tool](https://grafana.com/docs/mimir/latest/manage/tools/mimirtool/) and [Cortex tool](https://github.com/grafana/cortex-tools#cortextool) respectively. - -## Information - -### Version - -1.1.0 - -## Content negotiation - -### Consumes - -- application/json - -### Produces - -- application/json -- text/yaml -- application/yaml - -## All endpoints - -### Alert rules - -| Method | URI | Name | Summary | -| ------ | ---------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------- | -| DELETE | /api/v1/provisioning/alert-rules/:uid | [route delete alert rule](#route-delete-alert-rule) | Delete a specific alert rule by UID. | -| GET | /api/v1/provisioning/alert-rules/:uid | [route get alert rule](#route-get-alert-rule) | Get a specific alert rule by UID. | -| GET | /api/v1/provisioning/alert-rules/:uid/export | [route get alert rule export](#route-get-alert-rule-export) | Export an alert rule in provisioning file format. | -| GET | /api/v1/provisioning/folder/:folderUid/rule-groups/:group | [route get alert rule group](#route-get-alert-rule-group) | Get a rule group. | -| GET | /api/v1/provisioning/folder/:folderUid/rule-groups/:group/export | [route get alert rule group export](#route-get-alert-rule-group-export) | Export an alert rule group in provisioning file format. | -| GET | /api/v1/provisioning/alert-rules | [route get alert rules](#route-get-alert-rules) | Get all the alert rules. | -| GET | /api/v1/provisioning/alert-rules/export | [route get alert rules export](#route-get-alert-rules-export) | Export all alert rules in provisioning file format. | -| POST | /api/v1/provisioning/alert-rules | [route post alert rule](#route-post-alert-rule) | Create a new alert rule. | -| PUT | /api/v1/provisioning/alert-rules/:uid | [route put alert rule](#route-put-alert-rule) | Update an existing alert rule. | -| PUT | /api/v1/provisioning/folder/:folderUid/rule-groups/:group | [route put alert rule group](#route-put-alert-rule-group) | Update the interval of a rule group or modify the rules of the group. | - -### Contact points - -| Method | URI | Name | Summary | -| ------ | ------------------------------------------ | ----------------------------------------------------------------- | ------------------------------------------------------ | -| DELETE | /api/v1/provisioning/contact-points/:uid | [route delete contactpoints](#route-delete-contactpoints) | Delete a contact point. | -| GET | /api/v1/provisioning/contact-points | [route get contactpoints](#route-get-contactpoints) | Get all the contact points. | -| GET | /api/v1/provisioning/contact-points/export | [route get contactpoints export](#route-get-contactpoints-export) | Export all contact points in provisioning file format. | -| POST | /api/v1/provisioning/contact-points | [route post contactpoints](#route-post-contactpoints) | Create a contact point. | -| PUT | /api/v1/provisioning/contact-points/:uid | [route put contactpoint](#route-put-contactpoint) | Update an existing contact point. | - -### Notification policies - -| Method | URI | Name | Summary | -| ------ | ------------------------------------ | ------------------------------------------------------------- | ---------------------------------------------------------------- | -| DELETE | /api/v1/provisioning/policies | [route reset policy tree](#route-reset-policy-tree) | Clears the notification policy tree. | -| GET | /api/v1/provisioning/policies | [route get policy tree](#route-get-policy-tree) | Get the notification policy tree. | -| GET | /api/v1/provisioning/policies/export | [route get policy tree export](#route-get-policy-tree-export) | Export the notification policy tree in provisioning file format. | -| PUT | /api/v1/provisioning/policies | [route put policy tree](#route-put-policy-tree) | Sets the notification policy tree. | - -### Mute timings - -| Method | URI | Name | Summary | -| ------ | --------------------------------------- | ----------------------------------------------------- | -------------------------------- | -| DELETE | /api/v1/provisioning/mute-timings/:name | [route delete mute timing](#route-delete-mute-timing) | Delete a mute timing. | -| GET | /api/v1/provisioning/mute-timings/:name | [route get mute timing](#route-get-mute-timing) | Get a mute timing. | -| GET | /api/v1/provisioning/mute-timings | [route get mute timings](#route-get-mute-timings) | Get all the mute timings. | -| POST | /api/v1/provisioning/mute-timings | [route post mute timing](#route-post-mute-timing) | Create a new mute timing. | -| PUT | /api/v1/provisioning/mute-timings/:name | [route put mute timing](#route-put-mute-timing) | Replace an existing mute timing. | - -### Templates - -| Method | URI | Name | Summary | -| ------ | ------------------------------------ | ----------------------------------------------- | ------------------------------------------ | -| DELETE | /api/v1/provisioning/templates/:name | [route delete template](#route-delete-template) | Delete a template. | -| GET | /api/v1/provisioning/templates/:name | [route get template](#route-get-template) | Get a notification template. | -| GET | /api/v1/provisioning/templates | [route get templates](#route-get-templates) | Get all notification templates. | -| PUT | /api/v1/provisioning/templates/:name | [route put template](#route-put-template) | Updates an existing notification template. | - -## Paths - -### Delete a specific alert rule by UID. (_RouteDeleteAlertRule_) - -``` -DELETE /api/v1/provisioning/alert-rules/:uid -``` - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | ------ | -------- | --------- | :------: | ------- | --------------------------------------------------------- | -| UID | `path` | string | `string` | | ✓ | | Alert rule UID | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ----------------------------------- | ---------- | ---------------------------------------- | :---------: | --------------------------------------------- | -| [204](#route-delete-alert-rule-204) | No Content | The alert rule was deleted successfully. | | [schema](#route-delete-alert-rule-204-schema) | - -#### Responses - -##### 204 - The alert rule was deleted successfully. - -Status: No Content - -###### Schema - -### Delete a contact point. (_RouteDeleteContactpoints_) - -``` -DELETE /api/v1/provisioning/contact-points/:uid -``` - -#### Consumes - -- application/json - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ------------------------------------------ | -| UID | `path` | string | `string` | | ✓ | | UID is the contact point unique identifier | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| -------------------------------------- | ---------- | ------------------------------------------- | :---------: | ------------------------------------------------ | -| [204](#route-delete-contactpoints-204) | No Content | The contact point was deleted successfully. | | [schema](#route-delete-contactpoints-204-schema) | - -#### Responses - -##### 204 - The contact point was deleted successfully. - -Status: No Content - -###### Schema - -### Delete a mute timing. (_RouteDeleteMuteTiming_) - -``` -DELETE /api/v1/provisioning/mute-timings/:name -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ---------------- | -| name | `path` | string | `string` | | ✓ | | Mute timing name | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ------------------------------------ | ---------- | ----------------------------------------- | :---------: | ---------------------------------------------- | -| [204](#route-delete-mute-timing-204) | No Content | The mute timing was deleted successfully. | | [schema](#route-delete-mute-timing-204-schema) | - -#### Responses - -##### 204 - The mute timing was deleted successfully. - -Status: No Content - -###### Schema - -### Delete a template. (_RouteDeleteTemplate_) - -``` -DELETE /api/v1/provisioning/templates/:name -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ------------- | -| name | `path` | string | `string` | | ✓ | | Template Name | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------- | ---------- | -------------------------------------- | :---------: | ------------------------------------------- | -| [204](#route-delete-template-204) | No Content | The template was deleted successfully. | | [schema](#route-delete-template-204-schema) | - -#### Responses - -##### 204 - The template was deleted successfully. - -Status: No Content - -###### Schema - -### Get a specific alert rule by UID. (_RouteGetAlertRule_) - -``` -GET /api/v1/provisioning/alert-rules/:uid -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| ---- | ------ | ------ | -------- | --------- | :------: | ------- | -------------- | -| UID | `path` | string | `string` | | ✓ | | Alert rule UID | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| -------------------------------- | --------- | -------------------- | :---------: | ------------------------------------------ | -| [200](#route-get-alert-rule-200) | OK | ProvisionedAlertRule | | [schema](#route-get-alert-rule-200-schema) | -| [404](#route-get-alert-rule-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-404-schema) | - -#### Responses - -##### 200 - ProvisionedAlertRule - -Status: OK - -###### Schema - -[ProvisionedAlertRule](#provisioned-alert-rule) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Export an alert rule in provisioning file format. (_RouteGetAlertRuleExport_) - -``` -GET /api/v1/provisioning/alert-rules/:uid/export -``` - -#### Produces - -- application/json -- application/yaml -- text/yaml - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------- | ------- | ------- | -------- | --------- | :------: | -------- | --------------------------------------------------------------------------------------------------------------------------------- | -| UID | `path` | string | `string` | | ✓ | | Alert rule UID | -| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | -| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------------- | --------- | ------------------ | :---------: | ------------------------------------------------- | -| [200](#route-get-alert-rule-export-200) | OK | AlertingFileExport | | [schema](#route-get-alert-rule-export-200-schema) | -| [404](#route-get-alert-rule-export-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-export-404-schema) | - -#### Responses - -##### 200 - AlertingFileExport - -Status: OK - -###### Schema - -[AlertingFileExport](#alerting-file-export) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Get a rule group. (_RouteGetAlertRuleGroup_) - -``` -GET /api/v1/provisioning/folder/:folderUid/rule-groups/:group -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| --------- | ------ | ------ | -------- | --------- | :------: | ------- | ----------- | -| FolderUID | `path` | string | `string` | | ✓ | | | -| Group | `path` | string | `string` | | ✓ | | | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| -------------------------------------- | --------- | -------------- | :---------: | ------------------------------------------------ | -| [200](#route-get-alert-rule-group-200) | OK | AlertRuleGroup | | [schema](#route-get-alert-rule-group-200-schema) | -| [404](#route-get-alert-rule-group-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-group-404-schema) | - -#### Responses - -##### 200 - AlertRuleGroup - -Status: OK - -###### Schema - -[AlertRuleGroup](#alert-rule-group) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Export an alert rule group in provisioning file format. (_RouteGetAlertRuleGroupExport_) - -``` -GET /api/v1/provisioning/folder/:folderUid/rule-groups/:group/export -``` - -#### Produces - -- application/json -- application/yaml -- text/yaml - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| --------- | ------- | ------- | -------- | --------- | :------: | -------- | --------------------------------------------------------------------------------------------------------------------------------- | -| FolderUID | `path` | string | `string` | | ✓ | | | -| Group | `path` | string | `string` | | ✓ | | | -| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | -| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------------------- | --------- | ------------------ | :---------: | ------------------------------------------------------- | -| [200](#route-get-alert-rule-group-export-200) | OK | AlertingFileExport | | [schema](#route-get-alert-rule-group-export-200-schema) | -| [404](#route-get-alert-rule-group-export-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-group-export-404-schema) | - -#### Responses - -##### 200 - AlertingFileExport - -Status: OK - -###### Schema - -[AlertingFileExport](#alerting-file-export) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Get all the alert rules. (_RouteGetAlertRules_) - -``` -GET /api/v1/provisioning/alert-rules -``` - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------- | ------ | --------------------- | :---------: | ------------------------------------------- | -| [200](#route-get-alert-rules-200) | OK | ProvisionedAlertRules | | [schema](#route-get-alert-rules-200-schema) | - -#### Responses - -##### 200 - ProvisionedAlertRules - -Status: OK - -###### Schema - -[ProvisionedAlertRules](#provisioned-alert-rules) - -### Export all alert rules in provisioning file format. (_RouteGetAlertRulesExport_) - -``` -GET /api/v1/provisioning/alert-rules/export -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------- | ------- | ------- | -------- | --------- | :------: | -------- | --------------------------------------------------------------------------------------------------------------------------------- | -| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | -| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ---------------------------------------- | --------- | ------------------ | :---------: | -------------------------------------------------- | -| [200](#route-get-alert-rules-export-200) | OK | AlertingFileExport | | [schema](#route-get-alert-rules-export-200-schema) | -| [404](#route-get-alert-rules-export-404) | Not Found | Not found. | | [schema](#route-get-alert-rules-export-404-schema) | - -#### Responses - -##### 200 - AlertingFileExport - -Status: OK - -###### Schema - -[AlertingFileExport](#alerting-file-export) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Get all the contact points. (_RouteGetContactpoints_) - -``` -GET /api/v1/provisioning/contact-points -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| ---- | ------- | ------ | -------- | --------- | :------: | ------- | -------------- | -| name | `query` | string | `string` | | | | Filter by name | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ----------------------------------- | ------ | ------------- | :---------: | --------------------------------------------- | -| [200](#route-get-contactpoints-200) | OK | ContactPoints | | [schema](#route-get-contactpoints-200-schema) | - -#### Responses - -##### 200 - ContactPoints - -Status: OK - -###### Schema - -[ContactPoints](#contact-points) - -### Export all contact points in provisioning file format. (_RouteGetContactpointsExport_) - -``` -GET /api/v1/provisioning/contact-points/export -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------- | ------- | ------- | -------- | --------- | :------: | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| decrypt | `query` | boolean | `bool` | | | | Whether any contained secure settings should be decrypted or left redacted. Redacted settings will contain RedactedValue instead. Currently, only org admin can view decrypted secure settings. | -| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | -| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | -| name | `query` | string | `string` | | | | Filter by name | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ------------------------------------------ | --------- | ------------------ | :---------: | ---------------------------------------------------- | -| [200](#route-get-contactpoints-export-200) | OK | AlertingFileExport | | [schema](#route-get-contactpoints-export-200-schema) | -| [403](#route-get-contactpoints-export-403) | Forbidden | PermissionDenied | | [schema](#route-get-contactpoints-export-403-schema) | - -#### Responses - -##### 200 - AlertingFileExport - -Status: OK - -###### Schema - -[AlertingFileExport](#alerting-file-export) - -##### 403 - PermissionDenied - -Status: Forbidden - -###### Schema - -[PermissionDenied](#permission-denied) - -### Get a mute timing. (_RouteGetMuteTiming_) - -``` -GET /api/v1/provisioning/mute-timings/:name -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ---------------- | -| name | `path` | string | `string` | | ✓ | | Mute timing name | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------- | --------- | ---------------- | :---------: | ------------------------------------------- | -| [200](#route-get-mute-timing-200) | OK | MuteTimeInterval | | [schema](#route-get-mute-timing-200-schema) | -| [404](#route-get-mute-timing-404) | Not Found | Not found. | | [schema](#route-get-mute-timing-404-schema) | - -#### Responses - -##### 200 - MuteTimeInterval - -Status: OK - -###### Schema - -[MuteTimeInterval](#mute-time-interval) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Get all the mute timings. (_RouteGetMuteTimings_) - -``` -GET /api/v1/provisioning/mute-timings -``` - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ---------------------------------- | ------ | ----------- | :---------: | -------------------------------------------- | -| [200](#route-get-mute-timings-200) | OK | MuteTimings | | [schema](#route-get-mute-timings-200-schema) | - -#### Responses - -##### 200 - MuteTimings - -Status: OK - -###### Schema - -[MuteTimings](#mute-timings) - -### Get the notification policy tree. (_RouteGetPolicyTree_) - -``` -GET /api/v1/provisioning/policies -``` - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------- | ------ | ----------- | :---------: | ------------------------------------------- | -| [200](#route-get-policy-tree-200) | OK | Route | | [schema](#route-get-policy-tree-200-schema) | - -#### Responses - -##### 200 - Route - -Status: OK - -###### Schema - -[Route](#route) - -### Export the notification policy tree in provisioning file format. (_RouteGetPolicyTreeExport_) - -``` -GET /api/v1/provisioning/policies/export -``` - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ---------------------------------------- | --------- | ------------------ | :---------: | -------------------------------------------------- | -| [200](#route-get-policy-tree-export-200) | OK | AlertingFileExport | | [schema](#route-get-policy-tree-export-200-schema) | -| [404](#route-get-policy-tree-export-404) | Not Found | NotFound | | [schema](#route-get-policy-tree-export-404-schema) | - -#### Responses - -##### 200 - AlertingFileExport - -Status: OK - -###### Schema - -[AlertingFileExport](#alerting-file-export) - -##### 404 - NotFound - -Status: Not Found - -###### Schema - -[NotFound](#not-found) - -### Get a notification template. (_RouteGetTemplate_) - -``` -GET /api/v1/provisioning/templates/:name -``` - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ------------- | -| name | `path` | string | `string` | | ✓ | | Template Name | - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ------------------------------ | --------- | -------------------- | :---------: | ---------------------------------------- | -| [200](#route-get-template-200) | OK | NotificationTemplate | | [schema](#route-get-template-200-schema) | -| [404](#route-get-template-404) | Not Found | Not found. | | [schema](#route-get-template-404-schema) | - -#### Responses - -##### 200 - NotificationTemplate - -Status: OK - -###### Schema - -[NotificationTemplate](#notification-template) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Get all notification templates. (_RouteGetTemplates_) - -``` -GET /api/v1/provisioning/templates -``` - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ------------------------------- | --------- | --------------------- | :---------: | ----------------------------------------- | -| [200](#route-get-templates-200) | OK | NotificationTemplates | | [schema](#route-get-templates-200-schema) | -| [404](#route-get-templates-404) | Not Found | Not found. | | [schema](#route-get-templates-404-schema) | - -#### Responses - -##### 200 - NotificationTemplates - -Status: OK - -###### Schema - -[NotificationTemplates](#notification-templates) - -##### 404 - Not found. - -Status: Not Found - -###### Schema - -### Create a new alert rule. (_RoutePostAlertRule_) - -``` -POST /api/v1/provisioning/alert-rules -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [ProvisionedAlertRule](#provisioned-alert-rule) | `models.ProvisionedAlertRule` | | | | | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------- | ----------- | -------------------- | :---------: | ------------------------------------------- | -| [201](#route-post-alert-rule-201) | Created | ProvisionedAlertRule | | [schema](#route-post-alert-rule-201-schema) | -| [400](#route-post-alert-rule-400) | Bad Request | ValidationError | | [schema](#route-post-alert-rule-400-schema) | - -#### Responses - -##### 201 - ProvisionedAlertRule - -Status: Created - -###### Schema - -[ProvisionedAlertRule](#provisioned-alert-rule) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Create a contact point. (_RoutePostContactpoints_) - -``` -POST /api/v1/provisioning/contact-points -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [EmbeddedContactPoint](#embedded-contact-point) | `models.EmbeddedContactPoint` | | | | | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ------------------------------------ | ----------- | -------------------- | :---------: | ---------------------------------------------- | -| [202](#route-post-contactpoints-202) | Accepted | EmbeddedContactPoint | | [schema](#route-post-contactpoints-202-schema) | -| [400](#route-post-contactpoints-400) | Bad Request | ValidationError | | [schema](#route-post-contactpoints-400-schema) | - -#### Responses - -##### 202 - EmbeddedContactPoint - -Status: Accepted - -###### Schema - -[EmbeddedContactPoint](#embedded-contact-point) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Create a new mute timing. (_RoutePostMuteTiming_) - -``` -POST /api/v1/provisioning/mute-timings -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | --------------------------------------- | ------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [MuteTimeInterval](#mute-time-interval) | `models.MuteTimeInterval` | | | | | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ---------------------------------- | ----------- | ---------------- | :---------: | -------------------------------------------- | -| [201](#route-post-mute-timing-201) | Created | MuteTimeInterval | | [schema](#route-post-mute-timing-201-schema) | -| [400](#route-post-mute-timing-400) | Bad Request | ValidationError | | [schema](#route-post-mute-timing-400-schema) | - -#### Responses - -##### 201 - MuteTimeInterval - -Status: Created - -###### Schema - -[MuteTimeInterval](#mute-time-interval) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Update an existing alert rule. (_RoutePutAlertRule_) - -``` -PUT /api/v1/provisioning/alert-rules/:uid -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | -| UID | `path` | string | `string` | | ✓ | | Alert rule UID | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [ProvisionedAlertRule](#provisioned-alert-rule) | `models.ProvisionedAlertRule` | | | | | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| -------------------------------- | ----------- | -------------------- | :---------: | ------------------------------------------ | -| [200](#route-put-alert-rule-200) | OK | ProvisionedAlertRule | | [schema](#route-put-alert-rule-200-schema) | -| [400](#route-put-alert-rule-400) | Bad Request | ValidationError | | [schema](#route-put-alert-rule-400-schema) | - -#### Responses - -##### 200 - ProvisionedAlertRule - -Status: OK - -###### Schema - -[ProvisionedAlertRule](#provisioned-alert-rule) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Update the interval or alert rules of a rule group. (_RoutePutAlertRuleGroup_) - -``` -PUT /api/v1/provisioning/folder/:folderUid/rule-groups/:group -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | ----------------------------------- | ----------------------- | --------- | :------: | ------- | ------------------------------------------------------------------------------------------------------- | -| FolderUID | `path` | string | `string` | | ✓ | | | -| Group | `path` | string | `string` | | ✓ | | | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [AlertRuleGroup](#alert-rule-group) | `models.AlertRuleGroup` | | | | This action is idempotent and rules included in this body will overwrite configured rules for the group | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| -------------------------------------- | ----------- | --------------- | :---------: | ------------------------------------------------ | -| [200](#route-put-alert-rule-group-200) | OK | AlertRuleGroup | | [schema](#route-put-alert-rule-group-200-schema) | -| [400](#route-put-alert-rule-group-400) | Bad Request | ValidationError | | [schema](#route-put-alert-rule-group-400-schema) | - -#### Responses - -##### 200 - AlertRuleGroup - -Status: OK - -###### Schema - -[AlertRuleGroup](#alert-rule-group) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Update an existing contact point. (_RoutePutContactpoint_) - -``` -PUT /api/v1/provisioning/contact-points/:uid -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | -| UID | `path` | string | `string` | | ✓ | | UID is the contact point unique identifier | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [EmbeddedContactPoint](#embedded-contact-point) | `models.EmbeddedContactPoint` | | | | | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ---------------------------------- | ----------- | --------------- | :---------: | -------------------------------------------- | -| [202](#route-put-contactpoint-202) | Accepted | Ack | | [schema](#route-put-contactpoint-202-schema) | -| [400](#route-put-contactpoint-400) | Bad Request | ValidationError | | [schema](#route-put-contactpoint-400-schema) | - -#### Responses - -##### 202 - Ack - -Status: Accepted - -###### Schema - -[Ack](#ack) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Replace an existing mute timing. (_RoutePutMuteTiming_) - -``` -PUT /api/v1/provisioning/mute-timings/:name -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | --------------------------------------- | ------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | -| name | `path` | string | `string` | | ✓ | | Mute timing name | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [MuteTimeInterval](#mute-time-interval) | `models.MuteTimeInterval` | | | | | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------- | ----------- | ---------------- | :---------: | ------------------------------------------- | -| [200](#route-put-mute-timing-200) | OK | MuteTimeInterval | | [schema](#route-put-mute-timing-200-schema) | -| [400](#route-put-mute-timing-400) | Bad Request | ValidationError | | [schema](#route-put-mute-timing-400-schema) | - -#### Responses - -##### 200 - MuteTimeInterval - -Status: OK - -###### Schema - -[MuteTimeInterval](#mute-time-interval) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Sets the notification policy tree. (_RoutePutPolicyTree_) - -``` -PUT /api/v1/provisioning/policies -``` - -#### Consumes - -- application/json - -#### Parameters - -{{% responsive-table %}} - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | --------------- | -------------- | --------- | :------: | ------- | --------------------------------------------------------- | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [Route](#route) | `models.Route` | | | | The new notification routing tree to use | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| --------------------------------- | ----------- | --------------- | :---------: | ------------------------------------------- | -| [202](#route-put-policy-tree-202) | Accepted | Ack | | [schema](#route-put-policy-tree-202-schema) | -| [400](#route-put-policy-tree-400) | Bad Request | ValidationError | | [schema](#route-put-policy-tree-400-schema) | - -#### Responses - -##### 202 - Ack - -Status: Accepted - -###### Schema - -[Ack](#ack) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Updates an existing notification template. (_RoutePutTemplate_) - -``` -PUT /api/v1/provisioning/templates/:name -``` - -#### Consumes - -- application/json - -{{% responsive-table %}} - -#### Parameters - -| Name | Source | Type | Go type | Separator | Required | Default | Description | -| -------------------------- | -------- | ------------------------------------------------------------- | ------------------------------------ | --------- | :------: | ------- | --------------------------------------------------------- | -| name | `path` | string | `string` | | ✓ | | Template Name | -| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | -| Body | `body` | [NotificationTemplateContent](#notification-template-content) | `models.NotificationTemplateContent` | | | | | - -{{% /responsive-table %}} - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ------------------------------ | ----------- | -------------------- | :---------: | ---------------------------------------- | -| [202](#route-put-template-202) | Accepted | NotificationTemplate | | [schema](#route-put-template-202-schema) | -| [400](#route-put-template-400) | Bad Request | ValidationError | | [schema](#route-put-template-400-schema) | - -#### Responses - -##### 202 - NotificationTemplate - -Status: Accepted - -###### Schema - -[NotificationTemplate](#notification-template) - -##### 400 - ValidationError - -Status: Bad Request - -###### Schema - -[ValidationError](#validation-error) - -### Clears the notification policy tree. (_RouteResetPolicyTree_) - -``` -DELETE /api/v1/provisioning/policies -``` - -#### Consumes - -- application/json - -#### All responses - -| Code | Status | Description | Has headers | Schema | -| ----------------------------------- | -------- | ----------- | :---------: | --------------------------------------------- | -| [202](#route-reset-policy-tree-202) | Accepted | Ack | | [schema](#route-reset-policy-tree-202-schema) | - -#### Responses - -##### 202 - Ack - -Status: Accepted - -###### Schema - -[Ack](#ack) - -## Models - -### Ack - -[interface{}](#interface) - -### AlertQuery - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| --------------------------------------------------------- | ----------------------------------------- | ------------------- | :------: | ------- | ------------------------------------------------------------------------------------------------------ | ------- | -| datasourceUid | string | `string` | | | Grafana data source unique identifier; it should be '**expr**' for a Server Side Expression operation. | | -| model | [interface{}](#interface) | `interface{}` | | | JSON is the raw JSON query and includes the above properties as well as custom properties. | | -| queryType | string | `string` | | | QueryType is an optional identifier for the type of query. | -| It can be used to distinguish different types of queries. | | -| refId | string | `string` | | | RefID is the unique identifier of the query, set by the frontend call. | | -| relativeTimeRange | [RelativeTimeRange](#relative-time-range) | `RelativeTimeRange` | | | | | - -{{% /responsive-table %}} - -### AlertQueryExport - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ----------------- | ----------------------------------------- | ------------------- | :------: | ------- | ----------- | ------- | -| datasourceUid | string | `string` | | | | | -| model | [interface{}](#interface) | `interface{}` | | | | | -| queryType | string | `string` | | | | | -| refId | string | `string` | | | | | -| relativeTimeRange | [RelativeTimeRange](#relative-time-range) | `RelativeTimeRange` | | | | | - -{{% /responsive-table %}} - -### AlertRuleExport - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ------------ | ----------------------------------------- | --------------------- | :------: | ------- | ----------- | ------- | -| annotations | map of string | `map[string]string` | | | | | -| condition | string | `string` | | | | | -| dashboardUid | string | `string` | | | | | -| data | [][AlertQueryExport](#alert-query-export) | `[]*AlertQueryExport` | | | | | -| execErrState | string | `string` | | | | | -| for | [Duration](#duration) | `Duration` | | | | | -| isPaused | boolean | `bool` | | | | | -| labels | map of string | `map[string]string` | | | | | -| noDataState | string | `string` | | | | | -| panelId | int64 (formatted integer) | `int64` | | | | | -| title | string | `string` | | | | | -| uid | string | `string` | | | | | - -{{% /responsive-table %}} - -### AlertRuleGroup - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| --------- | ------------------------------------------------- | ------------------------- | :------: | ------- | ----------- | ------- | -| folderUid | string | `string` | | | | | -| interval | int64 (formatted integer) | `int64` | | | | | -| rules | [][ProvisionedAlertRule](#provisioned-alert-rule) | `[]*ProvisionedAlertRule` | | | | | -| title | string | `string` | | | | | - -{{% /responsive-table %}} - -### AlertRuleGroupExport - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| -------- | --------------------------------------- | -------------------- | :------: | ------- | ----------- | ------- | -| folder | string | `string` | | | | | -| interval | [Duration](#duration) | `Duration` | | | | | -| name | string | `string` | | | | | -| orgId | int64 (formatted integer) | `int64` | | | | | -| rules | [][AlertRuleExport](#alert-rule-export) | `[]*AlertRuleExport` | | | | | - -{{% /responsive-table %}} - -### AlertingFileExport - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ------------- | --------------------------------------------------------- | ----------------------------- | :------: | ------- | ----------- | ------- | -| apiVersion | int64 (formatted integer) | `int64` | | | | | -| contactPoints | [][ContactPointExport](#contact-point-export) | `[]*ContactPointExport` | | | | | -| groups | [][AlertRuleGroupExport](#alert-rule-group-export) | `[]*AlertRuleGroupExport` | | | | | -| policies | [][NotificationPolicyExport](#notification-policy-export) | `[]*NotificationPolicyExport` | | | | | - -{{% /responsive-table %}} - -### ContactPointExport - -**Properties** - -| Name | Type | Go type | Required | Default | Description | Example | -| --------- | ------------------------------------ | ------------------- | :------: | ------- | ----------- | ------- | -| name | string | `string` | | | | | -| orgId | int64 (formatted integer) | `int64` | | | | | -| receivers | [][ReceiverExport](#receiver-export) | `[]*ReceiverExport` | | | | | - -### ContactPoints - -[][EmbeddedContactPoint](#embedded-contact-point) - -### Duration - -| Name | Type | Go type | Default | Description | Example | -| -------- | ------------------------- | ------- | ------- | ----------- | ------- | -| Duration | int64 (formatted integer) | int64 | | | | - -### EmbeddedContactPoint - -> EmbeddedContactPoint is the contact point type that is used -> by grafanas embedded alertmanager implementation. - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ------------------------------------ | ----------------------- | -------- | :------: | ------- | ----------------------------------------------------------------- | --------- | -| disableResolveMessage | boolean | `bool` | | | | `false` | -| name | string | `string` | | | Name is used as grouping key in the UI. Contact points with the | -| same name will be grouped in the UI. | `webhook_1` | -| provenance | string | `string` | | | | | -| settings | [JSON](#json) | `JSON` | ✓ | | | | -| type | string | `string` | ✓ | | | `webhook` | -| uid | string | `string` | | | UID is the unique identifier of the contact point. The UID can be | -| set by the user. | `my_external_reference` | - -{{% /responsive-table %}} - -### Json - -[interface{}](#interface) - -### MatchRegexps - -[MatchRegexps](#match-regexps) - -### MatchType - -| Name | Type | Go type | Default | Description | Example | -| --------- | ------------------------- | ------- | ------- | ----------- | ------- | -| MatchType | int64 (formatted integer) | int64 | | | | - -### Matcher - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ----- | ------------------------ | ----------- | :------: | ------- | ----------- | ------- | -| Name | string | `string` | | | | | -| Type | [MatchType](#match-type) | `MatchType` | | | | | -| Value | string | `string` | | | | | - -{{% /responsive-table %}} - -### Matchers - -> Matchers is a slice of Matchers that is sortable, implements Stringer, and -> provides a Matches method to match a LabelSet against all Matchers in the -> slice. Note that some users of Matchers might require it to be sorted. - -[][Matcher](#matcher) - -### MuteTimeInterval - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| -------------- | -------------------------------- | ----------------- | :------: | ------- | ----------- | ------- | -| name | string | `string` | | | | | -| time_intervals | [][TimeInterval](#time-interval) | `[]*TimeInterval` | | | | | - -{{% /responsive-table %}} - -### MuteTimings - -[][MuteTimeInterval](#mute-time-interval) - -### NotFound - -[interface{}](#interface) - -### NotificationPolicyExport - -**Properties** - -| Name | Type | Go type | Required | Default | Description | Example | -| ------ | ---------------------------- | ------------- | :------: | ------- | ----------- | ------- | -| Policy | [RouteExport](#route-export) | `RouteExport` | | | inline | | -| orgId | int64 (formatted integer) | `int64` | | | | | - -### NotificationTemplate - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ---------- | ------------------------- | ------------ | :------: | ------- | ----------- | ------- | -| name | string | `string` | | | | | -| provenance | [Provenance](#provenance) | `Provenance` | | | | | -| template | string | `string` | | | | | - -{{% /responsive-table %}} - -### NotificationTemplateContent - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| -------- | ------ | -------- | :------: | ------- | ----------- | ------- | -| template | string | `string` | | | | | - -{{% /responsive-table %}} - -### NotificationTemplates - -[][NotificationTemplate](#notification-template) - -### ObjectMatchers - -[Matchers](#matchers) - -#### Inlined models - -### PermissionDenied - -[interface{}](#interface) - -### Provenance - -| Name | Type | Go type | Default | Description | Example | -| ---------- | ------ | ------- | ------- | ----------- | ------- | -| Provenance | string | string | | | | - -### ProvisionedAlertRule - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ------------ | ---------------------------- | ------------------- | :------: | ------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| annotations | map of string | `map[string]string` | | | | `{"runbook_url":"https://supercoolrunbook.com/page/13"}` | -| condition | string | `string` | ✓ | | | `A` | -| data | [][AlertQuery](#alert-query) | `[]*AlertQuery` | ✓ | | | `[{"datasourceUid":"__expr__","model":{"conditions":[{"evaluator":{"params":[0,0],"type":"gt"},"operator":{"type":"and"},"query":{"params":[]},"reducer":{"params":[],"type":"avg"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1 == 1","hide":false,"intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"},"queryType":"","refId":"A","relativeTimeRange":{"from":0,"to":0}}]` | -| execErrState | string | `string` | ✓ | | | | -| folderUID | string | `string` | ✓ | | | `project_x` | -| for | [Duration](#duration) | `Duration` | ✓ | | | | -| id | int64 (formatted integer) | `int64` | | | | | -| isPaused | boolean | `bool` | | | | `false` | -| labels | map of string | `map[string]string` | | | | `{"team":"sre-team-1"}` | -| noDataState | string | `string` | ✓ | | | | -| orgID | int64 (formatted integer) | `int64` | ✓ | | | | -| provenance | [Provenance](#provenance) | `Provenance` | | | | | -| ruleGroup | string | `string` | ✓ | | | `eval_group_1` | -| title | string | `string` | ✓ | | | `Always firing` | -| uid | string | `string` | | | | | -| updated | date-time (formatted string) | `strfmt.DateTime` | | | | | - -{{% /responsive-table %}} - -### ProvisionedAlertRules - -[][ProvisionedAlertRule](#provisioned-alert-rule) - -### RawMessage - -[interface{}](#interface) - -### ReceiverExport - -**Properties** - -| Name | Type | Go type | Required | Default | Description | Example | -| --------------------- | -------------------------- | ------------ | :------: | ------- | ----------- | ------- | -| disableResolveMessage | boolean | `bool` | | | | | -| settings | [RawMessage](#raw-message) | `RawMessage` | | | | | -| type | string | `string` | | | | | -| uid | string | `string` | | | | | - -### Regexp - -> A Regexp is safe for concurrent use by multiple goroutines, -> except for configuration methods, such as Longest. - -[interface{}](#interface) - -### RelativeTimeRange - -> RelativeTimeRange is the per query start and end time -> for requests. - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ---- | --------------------- | ---------- | :------: | ------- | ----------- | ------- | -| from | [Duration](#duration) | `Duration` | | | | | -| to | [Duration](#duration) | `Duration` | | | | | - -{{% /responsive-table %}} - -### Route - -> A Route is a node that contains definitions of how to handle alerts. This is modified -> from the upstream alertmanager in that it adds the ObjectMatchers property. - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ------------------- | ---------------------------------- | ------------------- | :------: | ------- | --------------------------------------- | ------- | -| continue | boolean | `bool` | | | | | -| group_by | []string | `[]string` | | | | | -| group_interval | string | `string` | | | | | -| group_wait | string | `string` | | | | | -| match | map of string | `map[string]string` | | | Deprecated. Remove before v1.0 release. | | -| match_re | [MatchRegexps](#match-regexps) | `MatchRegexps` | | | | | -| matchers | [Matchers](#matchers) | `Matchers` | | | | | -| mute_time_intervals | []string | `[]string` | | | | | -| object_matchers | [ObjectMatchers](#object-matchers) | `ObjectMatchers` | | | | | -| provenance | [Provenance](#provenance) | `Provenance` | | | | | -| receiver | string | `string` | | | | | -| repeat_interval | string | `string` | | | | | -| routes | [][Route](#route) | `[]*Route` | | | | | - -{{% /responsive-table %}} - -### RouteExport - -> RouteExport is the provisioned file export of definitions.Route. This is needed to hide fields that aren't usable in -> provisioning file format. An alternative would be to define a custom MarshalJSON and MarshalYAML that excludes them. - -**Properties** - -| Name | Type | Go type | Required | Default | Description | Example | -| ------------------- | ---------------------------------- | ------------------- | :------: | ------- | --------------------------------------- | ------- | -| continue | boolean | `bool` | | | | | -| group_by | []string | `[]string` | | | | | -| group_interval | string | `string` | | | | | -| group_wait | string | `string` | | | | | -| match | map of string | `map[string]string` | | | Deprecated. Remove before v1.0 release. | | -| match_re | [MatchRegexps](#match-regexps) | `MatchRegexps` | | | | | -| matchers | [Matchers](#matchers) | `Matchers` | | | | | -| mute_time_intervals | []string | `[]string` | | | | | -| object_matchers | [ObjectMatchers](#object-matchers) | `ObjectMatchers` | | | | | -| receiver | string | `string` | | | | | -| repeat_interval | string | `string` | | | | | -| routes | [][RouteExport](#route-export) | `[]*RouteExport` | | | | | - -### TimeInterval - -> TimeInterval describes intervals of time. ContainsTime will tell you if a golang time is contained -> within the interval. - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ------------- | -------------------------- | -------------- | :------: | ------- | ----------- | ------- | -| days_of_month | []string | `[]string` | | | | | -| location | string | `string` | | | | | -| months | []string | `[]string` | | | | | -| times | [][TimeRange](#time-range) | `[]*TimeRange` | | | | | -| weekdays | []string | `[]string` | | | | | -| years | []string | `[]string` | | | | | - -{{% /responsive-table %}} - -### TimeRange - -> For example, 4:00PM to End of the day would Begin at 1020 and End at 1440. - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ----------- | ------------------------- | ------- | :------: | ------- | ----------- | ------- | -| EndMinute | int64 (formatted integer) | `int64` | | | | | -| StartMinute | int64 (formatted integer) | `int64` | | | | | - -{{% /responsive-table %}} - -### ValidationError - -**Properties** - -{{% responsive-table %}} - -| Name | Type | Go type | Required | Default | Description | Example | -| ---- | ------ | -------- | :------: | ------- | ----------- | --------------- | -| msg | string | `string` | | | | `error message` | - -{{% /responsive-table %}} +{{< docs/shared lookup="alerts/alerting_provisioning.md" source="grafana" version="latest" >}} diff --git a/docs/sources/shared/alerts/alerting_provisioning.md b/docs/sources/shared/alerts/alerting_provisioning.md new file mode 100644 index 00000000000..7be0b2d010c --- /dev/null +++ b/docs/sources/shared/alerts/alerting_provisioning.md @@ -0,0 +1,1622 @@ +--- +labels: + products: + - enterprise + - oss +title: 'Alerting Provisioning HTTP API ' +--- + +The Alerting provisioning API can be used to create, modify, and delete resources relevant to [Grafana Managed alerts]({{< relref "/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule" >}}). And is the one used by our [Grafana Terraform provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs). + +For managing resources related to [data source-managed alerts]({{< relref "/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule" >}}) including Recording Rules, you can use [Mimir tool](https://grafana.com/docs/mimir/latest/manage/tools/mimirtool/) and [Cortex tool](https://github.com/grafana/cortex-tools#cortextool) respectively. + +## Information + +### Version + +1.1.0 + +## Content negotiation + +### Consumes + +- application/json + +### Produces + +- application/json +- text/yaml +- application/yaml + +## All endpoints + +### Alert rules + +| Method | URI | Name | Summary | +| ------ | ---------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------- | +| DELETE | /api/v1/provisioning/alert-rules/:uid | [route delete alert rule](#route-delete-alert-rule) | Delete a specific alert rule by UID. | +| GET | /api/v1/provisioning/alert-rules/:uid | [route get alert rule](#route-get-alert-rule) | Get a specific alert rule by UID. | +| GET | /api/v1/provisioning/alert-rules/:uid/export | [route get alert rule export](#route-get-alert-rule-export) | Export an alert rule in provisioning file format. | +| GET | /api/v1/provisioning/folder/:folderUid/rule-groups/:group | [route get alert rule group](#route-get-alert-rule-group) | Get a rule group. | +| GET | /api/v1/provisioning/folder/:folderUid/rule-groups/:group/export | [route get alert rule group export](#route-get-alert-rule-group-export) | Export an alert rule group in provisioning file format. | +| GET | /api/v1/provisioning/alert-rules | [route get alert rules](#route-get-alert-rules) | Get all the alert rules. | +| GET | /api/v1/provisioning/alert-rules/export | [route get alert rules export](#route-get-alert-rules-export) | Export all alert rules in provisioning file format. | +| POST | /api/v1/provisioning/alert-rules | [route post alert rule](#route-post-alert-rule) | Create a new alert rule. | +| PUT | /api/v1/provisioning/alert-rules/:uid | [route put alert rule](#route-put-alert-rule) | Update an existing alert rule. | +| PUT | /api/v1/provisioning/folder/:folderUid/rule-groups/:group | [route put alert rule group](#route-put-alert-rule-group) | Update the interval of a rule group or modify the rules of the group. | + +#### Example alert rules template + +```json +{ + "title": "TEST-API_1", + "ruleGroup": "API", + "folderUID": "FOLDER", + "noDataState": "OK", + "execErrState": "OK", + "for": "5m", + "orgId": 1, + "uid": "", + "condition": "B", + "annotations": { + "summary": "test_api_1" + }, + "labels": { + "API": "test1" + }, + "data": [ + { + "refId": "A", + "queryType": "", + "relativeTimeRange": { + "from": 600, + "to": 0 + }, + "datasourceUid": " XXXXXXXXX-XXXXXXXXX-XXXXXXXXXX", + "model": { + "expr": "up", + "hide": false, + "intervalMs": 1000, + "maxDataPoints": 43200, + "refId": "A" + } + }, + { + "refId": "B", + "queryType": "", + "relativeTimeRange": { + "from": 0, + "to": 0 + }, + "datasourceUid": "-100", + "model": { + "conditions": [ + { + "evaluator": { + "params": [6], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": ["A"] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "datasource": { + "type": "__expr__", + "uid": "-100" + }, + "hide": false, + "intervalMs": 1000, + "maxDataPoints": 43200, + "refId": "B", + "type": "classic_conditions" + } + } + ] +} +``` + +### Contact points + +| Method | URI | Name | Summary | +| ------ | ------------------------------------------ | ----------------------------------------------------------------- | ------------------------------------------------------ | +| DELETE | /api/v1/provisioning/contact-points/:uid | [route delete contactpoints](#route-delete-contactpoints) | Delete a contact point. | +| GET | /api/v1/provisioning/contact-points | [route get contactpoints](#route-get-contactpoints) | Get all the contact points. | +| GET | /api/v1/provisioning/contact-points/export | [route get contactpoints export](#route-get-contactpoints-export) | Export all contact points in provisioning file format. | +| POST | /api/v1/provisioning/contact-points | [route post contactpoints](#route-post-contactpoints) | Create a contact point. | +| PUT | /api/v1/provisioning/contact-points/:uid | [route put contactpoint](#route-put-contactpoint) | Update an existing contact point. | + +### Notification policies + +| Method | URI | Name | Summary | +| ------ | ------------------------------------ | ------------------------------------------------------------- | ---------------------------------------------------------------- | +| DELETE | /api/v1/provisioning/policies | [route reset policy tree](#route-reset-policy-tree) | Clears the notification policy tree. | +| GET | /api/v1/provisioning/policies | [route get policy tree](#route-get-policy-tree) | Get the notification policy tree. | +| GET | /api/v1/provisioning/policies/export | [route get policy tree export](#route-get-policy-tree-export) | Export the notification policy tree in provisioning file format. | +| PUT | /api/v1/provisioning/policies | [route put policy tree](#route-put-policy-tree) | Sets the notification policy tree. | + +### Mute timings + +| Method | URI | Name | Summary | +| ------ | --------------------------------------- | ----------------------------------------------------- | -------------------------------- | +| DELETE | /api/v1/provisioning/mute-timings/:name | [route delete mute timing](#route-delete-mute-timing) | Delete a mute timing. | +| GET | /api/v1/provisioning/mute-timings/:name | [route get mute timing](#route-get-mute-timing) | Get a mute timing. | +| GET | /api/v1/provisioning/mute-timings | [route get mute timings](#route-get-mute-timings) | Get all the mute timings. | +| POST | /api/v1/provisioning/mute-timings | [route post mute timing](#route-post-mute-timing) | Create a new mute timing. | +| PUT | /api/v1/provisioning/mute-timings/:name | [route put mute timing](#route-put-mute-timing) | Replace an existing mute timing. | + +### Templates + +| Method | URI | Name | Summary | +| ------ | ------------------------------------ | ----------------------------------------------- | ------------------------------------------ | +| DELETE | /api/v1/provisioning/templates/:name | [route delete template](#route-delete-template) | Delete a template. | +| GET | /api/v1/provisioning/templates/:name | [route get template](#route-get-template) | Get a notification template. | +| GET | /api/v1/provisioning/templates | [route get templates](#route-get-templates) | Get all notification templates. | +| PUT | /api/v1/provisioning/templates/:name | [route put template](#route-put-template) | Updates an existing notification template. | + +## Edit resources in the Grafana UI + +By default, you cannot edit API-provisioned alerting resources in Grafana. To enable editing these resources in the Grafana UI, add the `X-Disable-Provenance` header to the following requests in the API: + +- `POST /api/v1/provisioning/alert-rules` +- `PUT /api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}` (calling this endpoint will change provenance for all alert rules within the alert group) +- `POST /api/v1/provisioning/contact-points` +- `POST /api/v1/provisioning/mute-timings` +- `PUT /api/v1/provisioning/policies` +- `PUT /api/v1/provisioning/templates/{name}` + +To reset the notification policy tree to the default and unlock it for editing in the Grafana UI, use the `DELETE /api/v1/provisioning/policies` endpoint. + +## Paths + +### Delete a specific alert rule by UID. (_RouteDeleteAlertRule_) + +``` +DELETE /api/v1/provisioning/alert-rules/:uid +``` + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | ------ | -------- | --------- | :------: | ------- | --------------------------------------------------------- | +| UID | `path` | string | `string` | | ✓ | | Alert rule UID | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ----------------------------------- | ---------- | ---------------------------------------- | :---------: | --------------------------------------------- | +| [204](#route-delete-alert-rule-204) | No Content | The alert rule was deleted successfully. | | [schema](#route-delete-alert-rule-204-schema) | + +#### Responses + +##### 204 - The alert rule was deleted successfully. + +Status: No Content + +###### Schema + +### Delete a contact point. (_RouteDeleteContactpoints_) + +``` +DELETE /api/v1/provisioning/contact-points/:uid +``` + +#### Consumes + +- application/json + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ------------------------------------------ | +| UID | `path` | string | `string` | | ✓ | | UID is the contact point unique identifier | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| -------------------------------------- | ---------- | ------------------------------------------- | :---------: | ------------------------------------------------ | +| [204](#route-delete-contactpoints-204) | No Content | The contact point was deleted successfully. | | [schema](#route-delete-contactpoints-204-schema) | + +#### Responses + +##### 204 - The contact point was deleted successfully. + +Status: No Content + +###### Schema + +### Delete a mute timing. (_RouteDeleteMuteTiming_) + +``` +DELETE /api/v1/provisioning/mute-timings/:name +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ---------------- | +| name | `path` | string | `string` | | ✓ | | Mute timing name | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ------------------------------------ | ---------- | ----------------------------------------- | :---------: | ---------------------------------------------- | +| [204](#route-delete-mute-timing-204) | No Content | The mute timing was deleted successfully. | | [schema](#route-delete-mute-timing-204-schema) | + +#### Responses + +##### 204 - The mute timing was deleted successfully. + +Status: No Content + +###### Schema + +### Delete a template. (_RouteDeleteTemplate_) + +``` +DELETE /api/v1/provisioning/templates/:name +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ------------- | +| name | `path` | string | `string` | | ✓ | | Template Name | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------- | ---------- | -------------------------------------- | :---------: | ------------------------------------------- | +| [204](#route-delete-template-204) | No Content | The template was deleted successfully. | | [schema](#route-delete-template-204-schema) | + +#### Responses + +##### 204 - The template was deleted successfully. + +Status: No Content + +###### Schema + +### Get a specific alert rule by UID. (_RouteGetAlertRule_) + +``` +GET /api/v1/provisioning/alert-rules/:uid +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| ---- | ------ | ------ | -------- | --------- | :------: | ------- | -------------- | +| UID | `path` | string | `string` | | ✓ | | Alert rule UID | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| -------------------------------- | --------- | -------------------- | :---------: | ------------------------------------------ | +| [200](#route-get-alert-rule-200) | OK | ProvisionedAlertRule | | [schema](#route-get-alert-rule-200-schema) | +| [404](#route-get-alert-rule-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-404-schema) | + +#### Responses + +##### 200 - ProvisionedAlertRule + +Status: OK + +###### Schema + +[ProvisionedAlertRule](#provisioned-alert-rule) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Export an alert rule in provisioning file format. (_RouteGetAlertRuleExport_) + +``` +GET /api/v1/provisioning/alert-rules/:uid/export +``` + +#### Produces + +- application/json +- application/yaml +- text/yaml + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------- | ------- | ------- | -------- | --------- | :------: | -------- | --------------------------------------------------------------------------------------------------------------------------------- | +| UID | `path` | string | `string` | | ✓ | | Alert rule UID | +| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | +| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------------- | --------- | ------------------ | :---------: | ------------------------------------------------- | +| [200](#route-get-alert-rule-export-200) | OK | AlertingFileExport | | [schema](#route-get-alert-rule-export-200-schema) | +| [404](#route-get-alert-rule-export-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-export-404-schema) | + +#### Responses + +##### 200 - AlertingFileExport + +Status: OK + +###### Schema + +[AlertingFileExport](#alerting-file-export) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Get a rule group. (_RouteGetAlertRuleGroup_) + +``` +GET /api/v1/provisioning/folder/:folderUid/rule-groups/:group +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| --------- | ------ | ------ | -------- | --------- | :------: | ------- | ----------- | +| FolderUID | `path` | string | `string` | | ✓ | | | +| Group | `path` | string | `string` | | ✓ | | | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| -------------------------------------- | --------- | -------------- | :---------: | ------------------------------------------------ | +| [200](#route-get-alert-rule-group-200) | OK | AlertRuleGroup | | [schema](#route-get-alert-rule-group-200-schema) | +| [404](#route-get-alert-rule-group-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-group-404-schema) | + +#### Responses + +##### 200 - AlertRuleGroup + +Status: OK + +###### Schema + +[AlertRuleGroup](#alert-rule-group) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Export an alert rule group in provisioning file format. (_RouteGetAlertRuleGroupExport_) + +``` +GET /api/v1/provisioning/folder/:folderUid/rule-groups/:group/export +``` + +#### Produces + +- application/json +- application/yaml +- text/yaml + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| --------- | ------- | ------- | -------- | --------- | :------: | -------- | --------------------------------------------------------------------------------------------------------------------------------- | +| FolderUID | `path` | string | `string` | | ✓ | | | +| Group | `path` | string | `string` | | ✓ | | | +| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | +| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------------------- | --------- | ------------------ | :---------: | ------------------------------------------------------- | +| [200](#route-get-alert-rule-group-export-200) | OK | AlertingFileExport | | [schema](#route-get-alert-rule-group-export-200-schema) | +| [404](#route-get-alert-rule-group-export-404) | Not Found | Not found. | | [schema](#route-get-alert-rule-group-export-404-schema) | + +#### Responses + +##### 200 - AlertingFileExport + +Status: OK + +###### Schema + +[AlertingFileExport](#alerting-file-export) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Get all the alert rules. (_RouteGetAlertRules_) + +``` +GET /api/v1/provisioning/alert-rules +``` + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------- | ------ | --------------------- | :---------: | ------------------------------------------- | +| [200](#route-get-alert-rules-200) | OK | ProvisionedAlertRules | | [schema](#route-get-alert-rules-200-schema) | + +#### Responses + +##### 200 - ProvisionedAlertRules + +Status: OK + +###### Schema + +[ProvisionedAlertRules](#provisioned-alert-rules) + +### Export all alert rules in provisioning file format. (_RouteGetAlertRulesExport_) + +``` +GET /api/v1/provisioning/alert-rules/export +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------- | ------- | ------- | -------- | --------- | :------: | -------- | --------------------------------------------------------------------------------------------------------------------------------- | +| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | +| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ---------------------------------------- | --------- | ------------------ | :---------: | -------------------------------------------------- | +| [200](#route-get-alert-rules-export-200) | OK | AlertingFileExport | | [schema](#route-get-alert-rules-export-200-schema) | +| [404](#route-get-alert-rules-export-404) | Not Found | Not found. | | [schema](#route-get-alert-rules-export-404-schema) | + +#### Responses + +##### 200 - AlertingFileExport + +Status: OK + +###### Schema + +[AlertingFileExport](#alerting-file-export) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Get all the contact points. (_RouteGetContactpoints_) + +``` +GET /api/v1/provisioning/contact-points +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| ---- | ------- | ------ | -------- | --------- | :------: | ------- | -------------- | +| name | `query` | string | `string` | | | | Filter by name | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ----------------------------------- | ------ | ------------- | :---------: | --------------------------------------------- | +| [200](#route-get-contactpoints-200) | OK | ContactPoints | | [schema](#route-get-contactpoints-200-schema) | + +#### Responses + +##### 200 - ContactPoints + +Status: OK + +###### Schema + +[ContactPoints](#contact-points) + +### Export all contact points in provisioning file format. (_RouteGetContactpointsExport_) + +``` +GET /api/v1/provisioning/contact-points/export +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------- | ------- | ------- | -------- | --------- | :------: | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| decrypt | `query` | boolean | `bool` | | | | Whether any contained secure settings should be decrypted or left redacted. Redacted settings will contain RedactedValue instead. Currently, only org admin can view decrypted secure settings. | +| download | `query` | boolean | `bool` | | | | Whether to initiate a download of the file or not. | +| format | `query` | string | `string` | | | `"yaml"` | Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence. | +| name | `query` | string | `string` | | | | Filter by name | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ------------------------------------------ | --------- | ------------------ | :---------: | ---------------------------------------------------- | +| [200](#route-get-contactpoints-export-200) | OK | AlertingFileExport | | [schema](#route-get-contactpoints-export-200-schema) | +| [403](#route-get-contactpoints-export-403) | Forbidden | PermissionDenied | | [schema](#route-get-contactpoints-export-403-schema) | + +#### Responses + +##### 200 - AlertingFileExport + +Status: OK + +###### Schema + +[AlertingFileExport](#alerting-file-export) + +##### 403 - PermissionDenied + +Status: Forbidden + +###### Schema + +[PermissionDenied](#permission-denied) + +### Get a mute timing. (_RouteGetMuteTiming_) + +``` +GET /api/v1/provisioning/mute-timings/:name +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ---------------- | +| name | `path` | string | `string` | | ✓ | | Mute timing name | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------- | --------- | ---------------- | :---------: | ------------------------------------------- | +| [200](#route-get-mute-timing-200) | OK | MuteTimeInterval | | [schema](#route-get-mute-timing-200-schema) | +| [404](#route-get-mute-timing-404) | Not Found | Not found. | | [schema](#route-get-mute-timing-404-schema) | + +#### Responses + +##### 200 - MuteTimeInterval + +Status: OK + +###### Schema + +[MuteTimeInterval](#mute-time-interval) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Get all the mute timings. (_RouteGetMuteTimings_) + +``` +GET /api/v1/provisioning/mute-timings +``` + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ---------------------------------- | ------ | ----------- | :---------: | -------------------------------------------- | +| [200](#route-get-mute-timings-200) | OK | MuteTimings | | [schema](#route-get-mute-timings-200-schema) | + +#### Responses + +##### 200 - MuteTimings + +Status: OK + +###### Schema + +[MuteTimings](#mute-timings) + +### Get the notification policy tree. (_RouteGetPolicyTree_) + +``` +GET /api/v1/provisioning/policies +``` + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------- | ------ | ----------- | :---------: | ------------------------------------------- | +| [200](#route-get-policy-tree-200) | OK | Route | | [schema](#route-get-policy-tree-200-schema) | + +#### Responses + +##### 200 - Route + +Status: OK + +###### Schema + +[Route](#route) + +### Export the notification policy tree in provisioning file format. (_RouteGetPolicyTreeExport_) + +``` +GET /api/v1/provisioning/policies/export +``` + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ---------------------------------------- | --------- | ------------------ | :---------: | -------------------------------------------------- | +| [200](#route-get-policy-tree-export-200) | OK | AlertingFileExport | | [schema](#route-get-policy-tree-export-200-schema) | +| [404](#route-get-policy-tree-export-404) | Not Found | NotFound | | [schema](#route-get-policy-tree-export-404-schema) | + +#### Responses + +##### 200 - AlertingFileExport + +Status: OK + +###### Schema + +[AlertingFileExport](#alerting-file-export) + +##### 404 - NotFound + +Status: Not Found + +###### Schema + +[NotFound](#not-found) + +### Get a notification template. (_RouteGetTemplate_) + +``` +GET /api/v1/provisioning/templates/:name +``` + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| ---- | ------ | ------ | -------- | --------- | :------: | ------- | ------------- | +| name | `path` | string | `string` | | ✓ | | Template Name | + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ------------------------------ | --------- | -------------------- | :---------: | ---------------------------------------- | +| [200](#route-get-template-200) | OK | NotificationTemplate | | [schema](#route-get-template-200-schema) | +| [404](#route-get-template-404) | Not Found | Not found. | | [schema](#route-get-template-404-schema) | + +#### Responses + +##### 200 - NotificationTemplate + +Status: OK + +###### Schema + +[NotificationTemplate](#notification-template) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Get all notification templates. (_RouteGetTemplates_) + +``` +GET /api/v1/provisioning/templates +``` + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ------------------------------- | --------- | --------------------- | :---------: | ----------------------------------------- | +| [200](#route-get-templates-200) | OK | NotificationTemplates | | [schema](#route-get-templates-200-schema) | +| [404](#route-get-templates-404) | Not Found | Not found. | | [schema](#route-get-templates-404-schema) | + +#### Responses + +##### 200 - NotificationTemplates + +Status: OK + +###### Schema + +[NotificationTemplates](#notification-templates) + +##### 404 - Not found. + +Status: Not Found + +###### Schema + +### Create a new alert rule. (_RoutePostAlertRule_) + +``` +POST /api/v1/provisioning/alert-rules +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [ProvisionedAlertRule](#provisioned-alert-rule) | `models.ProvisionedAlertRule` | | | | | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------- | ----------- | -------------------- | :---------: | ------------------------------------------- | +| [201](#route-post-alert-rule-201) | Created | ProvisionedAlertRule | | [schema](#route-post-alert-rule-201-schema) | +| [400](#route-post-alert-rule-400) | Bad Request | ValidationError | | [schema](#route-post-alert-rule-400-schema) | + +#### Responses + +##### 201 - ProvisionedAlertRule + +Status: Created + +###### Schema + +[ProvisionedAlertRule](#provisioned-alert-rule) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Create a contact point. (_RoutePostContactpoints_) + +``` +POST /api/v1/provisioning/contact-points +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [EmbeddedContactPoint](#embedded-contact-point) | `models.EmbeddedContactPoint` | | | | | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ------------------------------------ | ----------- | -------------------- | :---------: | ---------------------------------------------- | +| [202](#route-post-contactpoints-202) | Accepted | EmbeddedContactPoint | | [schema](#route-post-contactpoints-202-schema) | +| [400](#route-post-contactpoints-400) | Bad Request | ValidationError | | [schema](#route-post-contactpoints-400-schema) | + +#### Responses + +##### 202 - EmbeddedContactPoint + +Status: Accepted + +###### Schema + +[EmbeddedContactPoint](#embedded-contact-point) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Create a new mute timing. (_RoutePostMuteTiming_) + +``` +POST /api/v1/provisioning/mute-timings +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | --------------------------------------- | ------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [MuteTimeInterval](#mute-time-interval) | `models.MuteTimeInterval` | | | | | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ---------------------------------- | ----------- | ---------------- | :---------: | -------------------------------------------- | +| [201](#route-post-mute-timing-201) | Created | MuteTimeInterval | | [schema](#route-post-mute-timing-201-schema) | +| [400](#route-post-mute-timing-400) | Bad Request | ValidationError | | [schema](#route-post-mute-timing-400-schema) | + +#### Responses + +##### 201 - MuteTimeInterval + +Status: Created + +###### Schema + +[MuteTimeInterval](#mute-time-interval) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Update an existing alert rule. (_RoutePutAlertRule_) + +``` +PUT /api/v1/provisioning/alert-rules/:uid +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | +| UID | `path` | string | `string` | | ✓ | | Alert rule UID | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [ProvisionedAlertRule](#provisioned-alert-rule) | `models.ProvisionedAlertRule` | | | | | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| -------------------------------- | ----------- | -------------------- | :---------: | ------------------------------------------ | +| [200](#route-put-alert-rule-200) | OK | ProvisionedAlertRule | | [schema](#route-put-alert-rule-200-schema) | +| [400](#route-put-alert-rule-400) | Bad Request | ValidationError | | [schema](#route-put-alert-rule-400-schema) | + +#### Responses + +##### 200 - ProvisionedAlertRule + +Status: OK + +###### Schema + +[ProvisionedAlertRule](#provisioned-alert-rule) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Update the interval or alert rules of a rule group. (_RoutePutAlertRuleGroup_) + +``` +PUT /api/v1/provisioning/folder/:folderUid/rule-groups/:group +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | ----------------------------------- | ----------------------- | --------- | :------: | ------- | ------------------------------------------------------------------------------------------------------- | +| FolderUID | `path` | string | `string` | | ✓ | | | +| Group | `path` | string | `string` | | ✓ | | | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [AlertRuleGroup](#alert-rule-group) | `models.AlertRuleGroup` | | | | This action is idempotent and rules included in this body will overwrite configured rules for the group | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| -------------------------------------- | ----------- | --------------- | :---------: | ------------------------------------------------ | +| [200](#route-put-alert-rule-group-200) | OK | AlertRuleGroup | | [schema](#route-put-alert-rule-group-200-schema) | +| [400](#route-put-alert-rule-group-400) | Bad Request | ValidationError | | [schema](#route-put-alert-rule-group-400-schema) | + +#### Responses + +##### 200 - AlertRuleGroup + +Status: OK + +###### Schema + +[AlertRuleGroup](#alert-rule-group) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Update an existing contact point. (_RoutePutContactpoint_) + +``` +PUT /api/v1/provisioning/contact-points/:uid +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | ----------------------------------------------- | ----------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | +| UID | `path` | string | `string` | | ✓ | | UID is the contact point unique identifier | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [EmbeddedContactPoint](#embedded-contact-point) | `models.EmbeddedContactPoint` | | | | | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ---------------------------------- | ----------- | --------------- | :---------: | -------------------------------------------- | +| [202](#route-put-contactpoint-202) | Accepted | Ack | | [schema](#route-put-contactpoint-202-schema) | +| [400](#route-put-contactpoint-400) | Bad Request | ValidationError | | [schema](#route-put-contactpoint-400-schema) | + +#### Responses + +##### 202 - Ack + +Status: Accepted + +###### Schema + +[Ack](#ack) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Replace an existing mute timing. (_RoutePutMuteTiming_) + +``` +PUT /api/v1/provisioning/mute-timings/:name +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | --------------------------------------- | ------------------------- | --------- | :------: | ------- | --------------------------------------------------------- | +| name | `path` | string | `string` | | ✓ | | Mute timing name | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [MuteTimeInterval](#mute-time-interval) | `models.MuteTimeInterval` | | | | | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------- | ----------- | ---------------- | :---------: | ------------------------------------------- | +| [200](#route-put-mute-timing-200) | OK | MuteTimeInterval | | [schema](#route-put-mute-timing-200-schema) | +| [400](#route-put-mute-timing-400) | Bad Request | ValidationError | | [schema](#route-put-mute-timing-400-schema) | + +#### Responses + +##### 200 - MuteTimeInterval + +Status: OK + +###### Schema + +[MuteTimeInterval](#mute-time-interval) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Sets the notification policy tree. (_RoutePutPolicyTree_) + +``` +PUT /api/v1/provisioning/policies +``` + +#### Consumes + +- application/json + +#### Parameters + +{{% responsive-table %}} + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | --------------- | -------------- | --------- | :------: | ------- | --------------------------------------------------------- | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [Route](#route) | `models.Route` | | | | The new notification routing tree to use | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| --------------------------------- | ----------- | --------------- | :---------: | ------------------------------------------- | +| [202](#route-put-policy-tree-202) | Accepted | Ack | | [schema](#route-put-policy-tree-202-schema) | +| [400](#route-put-policy-tree-400) | Bad Request | ValidationError | | [schema](#route-put-policy-tree-400-schema) | + +#### Responses + +##### 202 - Ack + +Status: Accepted + +###### Schema + +[Ack](#ack) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Updates an existing notification template. (_RoutePutTemplate_) + +``` +PUT /api/v1/provisioning/templates/:name +``` + +#### Consumes + +- application/json + +{{% responsive-table %}} + +#### Parameters + +| Name | Source | Type | Go type | Separator | Required | Default | Description | +| -------------------------- | -------- | ------------------------------------------------------------- | ------------------------------------ | --------- | :------: | ------- | --------------------------------------------------------- | +| name | `path` | string | `string` | | ✓ | | Template Name | +| X-Disable-Provenance: true | `header` | string | `string` | | | | Allows editing of provisioned resources in the Grafana UI | +| Body | `body` | [NotificationTemplateContent](#notification-template-content) | `models.NotificationTemplateContent` | | | | | + +{{% /responsive-table %}} + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ------------------------------ | ----------- | -------------------- | :---------: | ---------------------------------------- | +| [202](#route-put-template-202) | Accepted | NotificationTemplate | | [schema](#route-put-template-202-schema) | +| [400](#route-put-template-400) | Bad Request | ValidationError | | [schema](#route-put-template-400-schema) | + +#### Responses + +##### 202 - NotificationTemplate + +Status: Accepted + +###### Schema + +[NotificationTemplate](#notification-template) + +##### 400 - ValidationError + +Status: Bad Request + +###### Schema + +[ValidationError](#validation-error) + +### Clears the notification policy tree. (_RouteResetPolicyTree_) + +``` +DELETE /api/v1/provisioning/policies +``` + +#### Consumes + +- application/json + +#### All responses + +| Code | Status | Description | Has headers | Schema | +| ----------------------------------- | -------- | ----------- | :---------: | --------------------------------------------- | +| [202](#route-reset-policy-tree-202) | Accepted | Ack | | [schema](#route-reset-policy-tree-202-schema) | + +#### Responses + +##### 202 - Ack + +Status: Accepted + +###### Schema + +[Ack](#ack) + +## Models + +### Ack + +[interface{}](#interface) + +### AlertQuery + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| --------------------------------------------------------- | ----------------------------------------- | ------------------- | :------: | ------- | ------------------------------------------------------------------------------------------------------ | ------- | +| datasourceUid | string | `string` | | | Grafana data source unique identifier; it should be '**expr**' for a Server Side Expression operation. | | +| model | [interface{}](#interface) | `interface{}` | | | JSON is the raw JSON query and includes the above properties as well as custom properties. | | +| queryType | string | `string` | | | QueryType is an optional identifier for the type of query. | +| It can be used to distinguish different types of queries. | | +| refId | string | `string` | | | RefID is the unique identifier of the query, set by the frontend call. | | +| relativeTimeRange | [RelativeTimeRange](#relative-time-range) | `RelativeTimeRange` | | | | | + +{{% /responsive-table %}} + +### AlertQueryExport + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ----------------- | ----------------------------------------- | ------------------- | :------: | ------- | ----------- | ------- | +| datasourceUid | string | `string` | | | | | +| model | [interface{}](#interface) | `interface{}` | | | | | +| queryType | string | `string` | | | | | +| refId | string | `string` | | | | | +| relativeTimeRange | [RelativeTimeRange](#relative-time-range) | `RelativeTimeRange` | | | | | + +{{% /responsive-table %}} + +### AlertRuleExport + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ------------ | ----------------------------------------- | --------------------- | :------: | ------- | ----------- | ------- | +| annotations | map of string | `map[string]string` | | | | | +| condition | string | `string` | | | | | +| dashboardUid | string | `string` | | | | | +| data | [][AlertQueryExport](#alert-query-export) | `[]*AlertQueryExport` | | | | | +| execErrState | string | `string` | | | | | +| for | [Duration](#duration) | `Duration` | | | | | +| isPaused | boolean | `bool` | | | | | +| labels | map of string | `map[string]string` | | | | | +| noDataState | string | `string` | | | | | +| panelId | int64 (formatted integer) | `int64` | | | | | +| title | string | `string` | | | | | +| uid | string | `string` | | | | | + +{{% /responsive-table %}} + +### AlertRuleGroup + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| --------- | ------------------------------------------------- | ------------------------- | :------: | ------- | ----------- | ------- | +| folderUid | string | `string` | | | | | +| interval | int64 (formatted integer) | `int64` | | | | | +| rules | [][ProvisionedAlertRule](#provisioned-alert-rule) | `[]*ProvisionedAlertRule` | | | | | +| title | string | `string` | | | | | + +{{% /responsive-table %}} + +### AlertRuleGroupExport + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| -------- | --------------------------------------- | -------------------- | :------: | ------- | ----------- | ------- | +| folder | string | `string` | | | | | +| interval | [Duration](#duration) | `Duration` | | | | | +| name | string | `string` | | | | | +| orgId | int64 (formatted integer) | `int64` | | | | | +| rules | [][AlertRuleExport](#alert-rule-export) | `[]*AlertRuleExport` | | | | | + +{{% /responsive-table %}} + +### AlertingFileExport + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ------------- | --------------------------------------------------------- | ----------------------------- | :------: | ------- | ----------- | ------- | +| apiVersion | int64 (formatted integer) | `int64` | | | | | +| contactPoints | [][ContactPointExport](#contact-point-export) | `[]*ContactPointExport` | | | | | +| groups | [][AlertRuleGroupExport](#alert-rule-group-export) | `[]*AlertRuleGroupExport` | | | | | +| policies | [][NotificationPolicyExport](#notification-policy-export) | `[]*NotificationPolicyExport` | | | | | + +{{% /responsive-table %}} + +### ContactPointExport + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +| --------- | ------------------------------------ | ------------------- | :------: | ------- | ----------- | ------- | +| name | string | `string` | | | | | +| orgId | int64 (formatted integer) | `int64` | | | | | +| receivers | [][ReceiverExport](#receiver-export) | `[]*ReceiverExport` | | | | | + +### ContactPoints + +[][EmbeddedContactPoint](#embedded-contact-point) + +### Duration + +| Name | Type | Go type | Default | Description | Example | +| -------- | ------------------------- | ------- | ------- | ----------- | ------- | +| Duration | int64 (formatted integer) | int64 | | | | + +### EmbeddedContactPoint + +> EmbeddedContactPoint is the contact point type that is used +> by grafanas embedded alertmanager implementation. + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ------------------------------------ | ----------------------- | -------- | :------: | ------- | ----------------------------------------------------------------- | --------- | +| disableResolveMessage | boolean | `bool` | | | | `false` | +| name | string | `string` | | | Name is used as grouping key in the UI. Contact points with the | +| same name will be grouped in the UI. | `webhook_1` | +| provenance | string | `string` | | | | | +| settings | [JSON](#json) | `JSON` | ✓ | | | | +| type | string | `string` | ✓ | | | `webhook` | +| uid | string | `string` | | | UID is the unique identifier of the contact point. The UID can be | +| set by the user. | `my_external_reference` | + +{{% /responsive-table %}} + +### Json + +[interface{}](#interface) + +### MatchRegexps + +[MatchRegexps](#match-regexps) + +### MatchType + +| Name | Type | Go type | Default | Description | Example | +| --------- | ------------------------- | ------- | ------- | ----------- | ------- | +| MatchType | int64 (formatted integer) | int64 | | | | + +### Matcher + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ----- | ------------------------ | ----------- | :------: | ------- | ----------- | ------- | +| Name | string | `string` | | | | | +| Type | [MatchType](#match-type) | `MatchType` | | | | | +| Value | string | `string` | | | | | + +{{% /responsive-table %}} + +### Matchers + +> Matchers is a slice of Matchers that is sortable, implements Stringer, and +> provides a Matches method to match a LabelSet against all Matchers in the +> slice. Note that some users of Matchers might require it to be sorted. + +[][Matcher](#matcher) + +### MuteTimeInterval + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| -------------- | -------------------------------- | ----------------- | :------: | ------- | ----------- | ------- | +| name | string | `string` | | | | | +| time_intervals | [][TimeInterval](#time-interval) | `[]*TimeInterval` | | | | | + +{{% /responsive-table %}} + +### MuteTimings + +[][MuteTimeInterval](#mute-time-interval) + +### NotFound + +[interface{}](#interface) + +### NotificationPolicyExport + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +| ------ | ---------------------------- | ------------- | :------: | ------- | ----------- | ------- | +| Policy | [RouteExport](#route-export) | `RouteExport` | | | inline | | +| orgId | int64 (formatted integer) | `int64` | | | | | + +### NotificationTemplate + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ---------- | ------------------------- | ------------ | :------: | ------- | ----------- | ------- | +| name | string | `string` | | | | | +| provenance | [Provenance](#provenance) | `Provenance` | | | | | +| template | string | `string` | | | | | + +{{% /responsive-table %}} + +### NotificationTemplateContent + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| -------- | ------ | -------- | :------: | ------- | ----------- | ------- | +| template | string | `string` | | | | | + +{{% /responsive-table %}} + +### NotificationTemplates + +[][NotificationTemplate](#notification-template) + +### ObjectMatchers + +[Matchers](#matchers) + +#### Inlined models + +### PermissionDenied + +[interface{}](#interface) + +### Provenance + +| Name | Type | Go type | Default | Description | Example | +| ---------- | ------ | ------- | ------- | ----------- | ------- | +| Provenance | string | string | | | | + +### ProvisionedAlertRule + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ------------ | ---------------------------- | ------------------- | :------: | ------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| annotations | map of string | `map[string]string` | | | | `{"runbook_url":"https://supercoolrunbook.com/page/13"}` | +| condition | string | `string` | ✓ | | | `A` | +| data | [][AlertQuery](#alert-query) | `[]*AlertQuery` | ✓ | | | `[{"datasourceUid":"__expr__","model":{"conditions":[{"evaluator":{"params":[0,0],"type":"gt"},"operator":{"type":"and"},"query":{"params":[]},"reducer":{"params":[],"type":"avg"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1 == 1","hide":false,"intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"},"queryType":"","refId":"A","relativeTimeRange":{"from":0,"to":0}}]` | +| execErrState | string | `string` | ✓ | | | | +| folderUID | string | `string` | ✓ | | | `project_x` | +| for | [Duration](#duration) | `Duration` | ✓ | | | | +| id | int64 (formatted integer) | `int64` | | | | | +| isPaused | boolean | `bool` | | | | `false` | +| labels | map of string | `map[string]string` | | | | `{"team":"sre-team-1"}` | +| noDataState | string | `string` | ✓ | | | | +| orgID | int64 (formatted integer) | `int64` | ✓ | | | | +| provenance | [Provenance](#provenance) | `Provenance` | | | | | +| ruleGroup | string | `string` | ✓ | | | `eval_group_1` | +| title | string | `string` | ✓ | | | `Always firing` | +| uid | string | `string` | | | | | +| updated | date-time (formatted string) | `strfmt.DateTime` | | | | | + +{{% /responsive-table %}} + +### ProvisionedAlertRules + +[][ProvisionedAlertRule](#provisioned-alert-rule) + +### RawMessage + +[interface{}](#interface) + +### ReceiverExport + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +| --------------------- | -------------------------- | ------------ | :------: | ------- | ----------- | ------- | +| disableResolveMessage | boolean | `bool` | | | | | +| settings | [RawMessage](#raw-message) | `RawMessage` | | | | | +| type | string | `string` | | | | | +| uid | string | `string` | | | | | + +### Regexp + +> A Regexp is safe for concurrent use by multiple goroutines, +> except for configuration methods, such as Longest. + +[interface{}](#interface) + +### RelativeTimeRange + +> RelativeTimeRange is the per query start and end time +> for requests. + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ---- | --------------------- | ---------- | :------: | ------- | ----------- | ------- | +| from | [Duration](#duration) | `Duration` | | | | | +| to | [Duration](#duration) | `Duration` | | | | | + +{{% /responsive-table %}} + +### Route + +> A Route is a node that contains definitions of how to handle alerts. This is modified +> from the upstream alertmanager in that it adds the ObjectMatchers property. + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ------------------- | ---------------------------------- | ------------------- | :------: | ------- | --------------------------------------- | ------- | +| continue | boolean | `bool` | | | | | +| group_by | []string | `[]string` | | | | | +| group_interval | string | `string` | | | | | +| group_wait | string | `string` | | | | | +| match | map of string | `map[string]string` | | | Deprecated. Remove before v1.0 release. | | +| match_re | [MatchRegexps](#match-regexps) | `MatchRegexps` | | | | | +| matchers | [Matchers](#matchers) | `Matchers` | | | | | +| mute_time_intervals | []string | `[]string` | | | | | +| object_matchers | [ObjectMatchers](#object-matchers) | `ObjectMatchers` | | | | | +| provenance | [Provenance](#provenance) | `Provenance` | | | | | +| receiver | string | `string` | | | | | +| repeat_interval | string | `string` | | | | | +| routes | [][Route](#route) | `[]*Route` | | | | | + +{{% /responsive-table %}} + +### RouteExport + +> RouteExport is the provisioned file export of definitions.Route. This is needed to hide fields that aren't usable in +> provisioning file format. An alternative would be to define a custom MarshalJSON and MarshalYAML that excludes them. + +**Properties** + +| Name | Type | Go type | Required | Default | Description | Example | +| ------------------- | ---------------------------------- | ------------------- | :------: | ------- | --------------------------------------- | ------- | +| continue | boolean | `bool` | | | | | +| group_by | []string | `[]string` | | | | | +| group_interval | string | `string` | | | | | +| group_wait | string | `string` | | | | | +| match | map of string | `map[string]string` | | | Deprecated. Remove before v1.0 release. | | +| match_re | [MatchRegexps](#match-regexps) | `MatchRegexps` | | | | | +| matchers | [Matchers](#matchers) | `Matchers` | | | | | +| mute_time_intervals | []string | `[]string` | | | | | +| object_matchers | [ObjectMatchers](#object-matchers) | `ObjectMatchers` | | | | | +| receiver | string | `string` | | | | | +| repeat_interval | string | `string` | | | | | +| routes | [][RouteExport](#route-export) | `[]*RouteExport` | | | | | + +### TimeInterval + +> TimeInterval describes intervals of time. ContainsTime will tell you if a golang time is contained +> within the interval. + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ------------- | -------------------------- | -------------- | :------: | ------- | ----------- | ------- | +| days_of_month | []string | `[]string` | | | | | +| location | string | `string` | | | | | +| months | []string | `[]string` | | | | | +| times | [][TimeRange](#time-range) | `[]*TimeRange` | | | | | +| weekdays | []string | `[]string` | | | | | +| years | []string | `[]string` | | | | | + +{{% /responsive-table %}} + +### TimeRange + +> For example, 4:00PM to End of the day would Begin at 1020 and End at 1440. + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ----------- | ------------------------- | ------- | :------: | ------- | ----------- | ------- | +| EndMinute | int64 (formatted integer) | `int64` | | | | | +| StartMinute | int64 (formatted integer) | `int64` | | | | | + +{{% /responsive-table %}} + +### ValidationError + +**Properties** + +{{% responsive-table %}} + +| Name | Type | Go type | Required | Default | Description | Example | +| ---- | ------ | -------- | :------: | ------- | ----------- | --------------- | +| msg | string | `string` | | | | `error message` | + +{{% /responsive-table %}} From 00e96e45847dbf280e6a6ebeed92e2a8b44d62b0 Mon Sep 17 00:00:00 2001 From: Misi Date: Mon, 12 Feb 2024 11:12:08 +0100 Subject: [PATCH 02/43] Auth: SSO Settings UI frontend improvements (#82264) * Add frontend fixes * Update labels + link --- .../auth-config/AuthProvidersListPage.tsx | 5 ++- .../auth-config/ProviderConfigForm.test.tsx | 4 ++- .../auth-config/ProviderConfigForm.tsx | 6 ++-- public/app/features/auth-config/fields.tsx | 32 +++++++++++++------ public/app/features/auth-config/types.ts | 1 + 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/public/app/features/auth-config/AuthProvidersListPage.tsx b/public/app/features/auth-config/AuthProvidersListPage.tsx index 77acdcc2c01..07a2e54fbb3 100644 --- a/public/app/features/auth-config/AuthProvidersListPage.tsx +++ b/public/app/features/auth-config/AuthProvidersListPage.tsx @@ -62,7 +62,10 @@ export const AuthConfigPageUnconnected = ({ subTitle={ <> Manage your auth settings and configure single sign-on. Find out more in our{' '} - + documentation . diff --git a/public/app/features/auth-config/ProviderConfigForm.test.tsx b/public/app/features/auth-config/ProviderConfigForm.test.tsx index ac76732075c..0386ab6e710 100644 --- a/public/app/features/auth-config/ProviderConfigForm.test.tsx +++ b/public/app/features/auth-config/ProviderConfigForm.test.tsx @@ -44,6 +44,7 @@ jest.mock('app/core/components/FormPrompt/FormPrompt', () => ({ const testConfig: SSOProvider = { id: '300f9b7c-0488-40db-9763-a22ce8bf6b3e', provider: 'github', + source: 'database', settings: { ...emptySettings, name: 'GitHub', @@ -101,7 +102,8 @@ describe('ProviderConfigForm', () => { expect(putMock).toHaveBeenCalledWith( '/api/v1/sso-settings/github', { - ...testConfig, + id: '300f9b7c-0488-40db-9763-a22ce8bf6b3e', + provider: 'github', settings: { name: 'GitHub', allowedOrganizations: 'test-org1,test-org2', diff --git a/public/app/features/auth-config/ProviderConfigForm.tsx b/public/app/features/auth-config/ProviderConfigForm.tsx index 184bbce65d9..17e0f24a6d5 100644 --- a/public/app/features/auth-config/ProviderConfigForm.tsx +++ b/public/app/features/auth-config/ProviderConfigForm.tsx @@ -82,7 +82,6 @@ export const ProviderConfigForm = ({ config, provider, isLoading }: ProviderConf payload: [message], }); setSubmitError(true); - } finally { setIsSaving(false); } }; @@ -182,7 +181,9 @@ export const ProviderConfigForm = ({ config, provider, isLoading }: ProviderConf )} - + @@ -192,6 +193,7 @@ export const ProviderConfigForm = ({ config, provider, isLoading }: ProviderConf - - )} - + + ); diff --git a/public/app/features/teams/TeamSettings.tsx b/public/app/features/teams/TeamSettings.tsx index 3b09298d72b..09165357279 100644 --- a/public/app/features/teams/TeamSettings.tsx +++ b/public/app/features/teams/TeamSettings.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; +import { useForm } from 'react-hook-form'; import { connect, ConnectedProps } from 'react-redux'; -import { Input, Field, Form, Button, FieldSet, VerticalGroup } from '@grafana/ui'; +import { Input, Field, Button, FieldSet, Stack } from '@grafana/ui'; import { TeamRolePicker } from 'app/core/components/RolePicker/TeamRolePicker'; import { updateTeamRoles } from 'app/core/components/RolePicker/api'; import { useRoleOptions } from 'app/core/components/RolePicker/hooks'; @@ -28,6 +29,11 @@ export const TeamSettings = ({ team, updateTeam }: Props) => { const [{ roleOptions }] = useRoleOptions(currentOrgId); const [pendingRoles, setPendingRoles] = useState([]); + const { + handleSubmit, + register, + formState: { errors }, + } = useForm({ defaultValues: team }); const canUpdateRoles = contextSrv.hasPermission(AccessControlAction.ActionTeamsRolesAdd) && @@ -37,59 +43,55 @@ export const TeamSettings = ({ team, updateTeam }: Props) => { contextSrv.hasPermissionInMetadata(AccessControlAction.ActionTeamsRolesList, team) && contextSrv.hasPermission(AccessControlAction.ActionRolesList); + const onSubmit = async (formTeam: Team) => { + if (contextSrv.licensedAccessControlEnabled() && canUpdateRoles) { + await updateTeamRoles(pendingRoles, team.id); + } + updateTeam(formTeam.name, formTeam.email || ''); + }; + return ( - -
{ - if (contextSrv.licensedAccessControlEnabled() && canUpdateRoles) { - await updateTeamRoles(pendingRoles, team.id); - } - updateTeam(formTeam.name, formTeam.email || ''); - }} - disabled={!canWriteTeamSettings} - > - {({ register, errors }) => ( -
- - - + + +
+ + + - {contextSrv.licensedAccessControlEnabled() && canListRoles && ( - - - - )} - - - + {contextSrv.licensedAccessControlEnabled() && canListRoles && ( + + - -
- )} - + )} + + + + + +
+ -
+ ); }; From 1abe4a02b483128129203f4560a3c4bab3a44a52 Mon Sep 17 00:00:00 2001 From: Ihor Yeromin Date: Tue, 13 Feb 2024 14:21:36 +0200 Subject: [PATCH 38/43] Table: Update page index on data update (#81574) * fix(table): page index reset on data update --- packages/grafana-ui/src/components/Table/Table.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/grafana-ui/src/components/Table/Table.tsx b/packages/grafana-ui/src/components/Table/Table.tsx index 7bb9e9cf976..774856991cd 100644 --- a/packages/grafana-ui/src/components/Table/Table.tsx +++ b/packages/grafana-ui/src/components/Table/Table.tsx @@ -237,6 +237,17 @@ export const Table = memo((props: Props) => { setPageSize(pageSize); }, [pageSize, setPageSize]); + useEffect(() => { + // Reset page index when data changes + // This is needed because react-table does not do this automatically + // autoResetPage is set to false because setting it to true causes the issue described in + // https://github.com/grafana/grafana/pull/67477 + if (data.length / pageSize < state.pageIndex) { + gotoPage(0); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [data]); + useResetVariableListSizeCache(extendedState, listRef, data, hasUniqueId); useFixScrollbarContainer(variableSizeListScrollbarRef, tableDivRef); From baa46e6a4658f74123d2e71a62f3f545768a65bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 13 Feb 2024 13:36:07 +0100 Subject: [PATCH 39/43] DasbhoardScene: Fixes panel menu new alert rule action (#82366) * DasbhoardScene: Fixes panel menu new alert rule action * Update --- .betterer.results | 5 ++-- .../scene/PanelMenuBehavior.tsx | 23 +++++-------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/.betterer.results b/.betterer.results index 4ac26099498..c4690e9daf2 100644 --- a/.betterer.results +++ b/.betterer.results @@ -2588,10 +2588,9 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], + [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"], - [0, 0, 0, "Do not use any type assertions.", "3"] + [0, 0, 0, "Do not use any type assertions.", "2"] ], "public/app/features/dashboard-scene/scene/setDashboardPanelContext.test.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] diff --git a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx index 0fe34d9bd9a..c3b105fa186 100644 --- a/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx +++ b/public/app/features/dashboard-scene/scene/PanelMenuBehavior.tsx @@ -11,7 +11,6 @@ import { config, getPluginLinkExtensions, locationService } from '@grafana/runti import { LocalValueVariable, SceneFlexLayout, - SceneGridItem, SceneGridLayout, SceneGridRow, SceneObject, @@ -22,16 +21,14 @@ import { import { DataQuery, OptionsWithLegend } from '@grafana/schema'; import appEvents from 'app/core/app_events'; import { t } from 'app/core/internationalization'; -import { panelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form'; +import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form'; import { shareDashboardType } from 'app/features/dashboard/components/ShareModal/utils'; -import { DashboardModel, PanelModel } from 'app/features/dashboard/state'; import { InspectTab } from 'app/features/inspector/types'; import { getScenePanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers'; import { createExtensionSubMenu } from 'app/features/plugins/extensions/utils'; import { addDataTrailPanelAction } from 'app/features/trails/dashboardIntegration'; import { ShowConfirmModalEvent } from 'app/types/events'; -import { gridItemToPanel, transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel'; import { ShareModal } from '../sharing/ShareModal'; import { DashboardInteractions } from '../utils/interactions'; import { getEditPanelUrl, getInspectUrl, getViewPanelUrl, tryGetExploreUrlForPanel } from '../utils/urlBuilders'; @@ -56,11 +53,6 @@ export function panelMenuBehavior(menu: VizPanelMenu) { const panelId = getPanelIdForVizPanel(panel); const dashboard = getDashboardSceneFor(panel); const { isEmbedded } = dashboard.state.meta; - const panelJson = gridItemToPanel(panel.parent as SceneGridItem); - const panelModel = new PanelModel(panelJson); - const dashboardJson = transformSceneToSaveModel(dashboard); - const dashboardModel = new DashboardModel(dashboardJson); - const exploreMenuItem = await getExploreMenuItem(panel); // For embedded dashboards we only have explore action for now @@ -138,7 +130,7 @@ export function panelMenuBehavior(menu: VizPanelMenu) { moreSubMenu.push({ text: t('panel.header-menu.new-alert-rule', `New alert rule`), - onClick: (e) => onCreateAlert(e, panelModel, dashboardModel), + onClick: (e) => onCreateAlert(panel), }); if (hasLegendOptions(panel.state.options)) { @@ -431,21 +423,18 @@ export function removePanel(dashboard: DashboardScene, panel: VizPanel, ask: boo } } -const onCreateAlert = (event: React.MouseEvent, panel: PanelModel, dashboard: DashboardModel) => { - event.preventDefault(); - createAlert(panel, dashboard); +const onCreateAlert = async (panel: VizPanel) => { DashboardInteractions.panelMenuItemClicked('create-alert'); -}; - -const createAlert = async (panel: PanelModel, dashboard: DashboardModel) => { - const formValues = await panelToRuleFormValues(panel, dashboard); + const formValues = await scenesPanelToRuleFormValues(panel); const ruleFormUrl = urlUtil.renderUrl('/alerting/new', { defaults: JSON.stringify(formValues), returnTo: location.pathname + location.search, }); locationService.push(ruleFormUrl); + + DashboardInteractions.panelMenuItemClicked('create-alert'); }; export function toggleVizPanelLegend(vizPanel: VizPanel): void { From 082f020b7d8d7a4c6d3d9d90810aa9216265989a Mon Sep 17 00:00:00 2001 From: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Date: Tue, 13 Feb 2024 13:44:08 +0100 Subject: [PATCH 40/43] Elasticsearch: Fix resource calls for paths that include `:` (#82327) * Elasticsearch: Fix resource calls for paths that include : * Add tests * Add test case and comment * Remove redundant comment --- pkg/tsdb/elasticsearch/elasticsearch.go | 24 ++++++++-------- pkg/tsdb/elasticsearch/elasticsearch_test.go | 30 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/pkg/tsdb/elasticsearch/elasticsearch.go b/pkg/tsdb/elasticsearch/elasticsearch.go index a60af5d9793..7a064154876 100644 --- a/pkg/tsdb/elasticsearch/elasticsearch.go +++ b/pkg/tsdb/elasticsearch/elasticsearch.go @@ -205,21 +205,11 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq return err } - esUrl, err := url.Parse(ds.URL) + esUrl, err := createElasticsearchURL(req, ds) if err != nil { - logger.Error("Failed to parse data source URL", "error", err, "url", ds.URL) - return err + logger.Error("Failed to create request url", "error", err, "url", ds.URL, "path", req.Path) } - resourcePath, err := url.Parse(req.Path) - if err != nil { - logger.Error("Failed to parse data source path", "error", err, "url", req.Path) - return err - } - - // We take the path and the query-string only - esUrl.RawQuery = resourcePath.RawQuery - esUrl.Path = path.Join(esUrl.Path, resourcePath.Path) request, err := http.NewRequestWithContext(ctx, req.Method, esUrl.String(), bytes.NewBuffer(req.Body)) if err != nil { logger.Error("Failed to create request", "error", err, "url", esUrl.String()) @@ -269,3 +259,13 @@ func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceReq Body: body, }) } + +func createElasticsearchURL(req *backend.CallResourceRequest, ds *es.DatasourceInfo) (*url.URL, error) { + esUrl, err := url.Parse(ds.URL) + if err != nil { + return nil, fmt.Errorf("failed to parse data source URL: %s, error: %w", ds.URL, err) + } + + esUrl.Path = path.Join(esUrl.Path, req.Path) + return esUrl, nil +} diff --git a/pkg/tsdb/elasticsearch/elasticsearch_test.go b/pkg/tsdb/elasticsearch/elasticsearch_test.go index 0434a79ae10..13a6aa79c71 100644 --- a/pkg/tsdb/elasticsearch/elasticsearch_test.go +++ b/pkg/tsdb/elasticsearch/elasticsearch_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/infra/httpclient" + es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client" ) type datasourceInfo struct { @@ -71,3 +72,32 @@ func TestNewInstanceSettings(t *testing.T) { }) }) } + +func TestCreateElasticsearchURL(t *testing.T) { + tt := []struct { + name string + settings es.DatasourceInfo + req backend.CallResourceRequest + expected string + }{ + {name: "with /_msearch path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "_msearch"}, expected: "http://localhost:9200/_msearch"}, + {name: "with _msearch path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "_msearch"}, expected: "http://localhost:9200/_msearch"}, + {name: "with _msearch path and valid url with /", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "_msearch"}, expected: "http://localhost:9200/_msearch"}, + {name: "with _mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "/_mapping"}, expected: "http://localhost:9200/_mapping"}, + {name: "with /_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "/_mapping"}, expected: "http://localhost:9200/_mapping"}, + {name: "with /_mapping path and valid url with /", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "/_mapping"}, expected: "http://localhost:9200/_mapping"}, + {name: "with abc/_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "abc/_mapping"}, expected: "http://localhost:9200/abc/_mapping"}, + {name: "with /abc/_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200"}, req: backend.CallResourceRequest{Path: "abc/_mapping"}, expected: "http://localhost:9200/abc/_mapping"}, + {name: "with /abc/_mapping path and valid url", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "abc/_mapping"}, expected: "http://localhost:9200/abc/_mapping"}, + // This is to support mappings to cross cluster search that includes ":" + {name: "with path including :", settings: es.DatasourceInfo{URL: "http://localhost:9200/"}, req: backend.CallResourceRequest{Path: "ab:c/_mapping"}, expected: "http://localhost:9200/ab:c/_mapping"}, + } + + for _, test := range tt { + t.Run(test.name, func(t *testing.T) { + url, err := createElasticsearchURL(&test.req, &test.settings) + require.NoError(t, err) + require.Equal(t, test.expected, url.String()) + }) + } +} From 763dab7532b1884ee02fc3ff94dd59615248af28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 13 Feb 2024 14:23:47 +0100 Subject: [PATCH 41/43] DashboardScene: Panel edit toolbar actions (#82302) * DashboardScene: Panel edit toolbar actions * Make saving work * Update public/app/features/dashboard-scene/panel-edit/PanelEditor.test.ts Co-authored-by: Dominik Prokop --------- Co-authored-by: Dominik Prokop --- .../panel-edit/PanelEditor.test.ts | 35 ++++++++++++- .../panel-edit/PanelEditor.tsx | 49 +++++-------------- .../panel-edit/PanelEditorRenderer.tsx | 30 ++---------- .../saving/getSaveDashboardChange.test.ts | 34 ++++++++++++- .../saving/getSaveDashboardChange.ts | 5 ++ .../scene/NavToolbarActions.tsx | 37 ++++++++++---- 6 files changed, 114 insertions(+), 76 deletions(-) diff --git a/public/app/features/dashboard-scene/panel-edit/PanelEditor.test.ts b/public/app/features/dashboard-scene/panel-edit/PanelEditor.test.ts index fef0c30dc0e..874d24c2257 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelEditor.test.ts +++ b/public/app/features/dashboard-scene/panel-edit/PanelEditor.test.ts @@ -1,5 +1,5 @@ import { PanelPlugin, PanelPluginMeta, PluginType } from '@grafana/data'; -import { SceneFlexItem, SplitLayout, VizPanel } from '@grafana/scenes'; +import { SceneFlexItem, SceneGridItem, SceneGridLayout, SplitLayout, VizPanel } from '@grafana/scenes'; import { DashboardScene } from '../scene/DashboardScene'; import { activateFullSceneTree } from '../utils/test-utils'; @@ -26,6 +26,37 @@ jest.mock('@grafana/runtime', () => ({ })); describe('PanelEditor', () => { + describe('When closing editor', () => { + it('should apply changes automatically', () => { + pluginToLoad = getTestPanelPlugin({ id: 'text', skipDataQuery: true }); + + const panel = new VizPanel({ + key: 'panel-1', + pluginId: 'text', + }); + + const editScene = buildPanelEditScene(panel); + const gridItem = new SceneGridItem({ body: panel }); + const scene = new DashboardScene({ + editPanel: editScene, + isEditing: true, + body: new SceneGridLayout({ + children: [gridItem], + }), + }); + + const deactivate = activateFullSceneTree(scene); + + const vizManager = editScene.state.panelRef.resolve(); + vizManager.state.panel.setState({ title: 'changed title' }); + + deactivate(); + + const updatedPanel = gridItem.state.body as VizPanel; + expect(updatedPanel?.state.title).toBe('changed title'); + }); + }); + describe('PanelDataPane', () => { it('should not exist if panel is skipDataQuery', () => { pluginToLoad = getTestPanelPlugin({ id: 'text', skipDataQuery: true }); @@ -44,7 +75,7 @@ describe('PanelEditor', () => { expect(((editScene.state.body as SplitLayout).state.primary as SplitLayout).state.secondary).toBeUndefined(); }); - it('should exist if panel is supporting querying', () => { + it('should exist if panel is supporting querying', () => { pluginToLoad = getTestPanelPlugin({ id: 'timeseries' }); const panel = new VizPanel({ diff --git a/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx b/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx index 415c7ac7b6a..e7e22365769 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelEditor.tsx @@ -14,7 +14,6 @@ import { VizPanel, } from '@grafana/scenes'; -import { getDashboardUrl } from '../utils/urlBuilders'; import { findVizPanelByKey, getDashboardSceneFor, @@ -38,8 +37,18 @@ export interface PanelEditorState extends SceneObjectState { export class PanelEditor extends SceneObjectBase { static Component = PanelEditorRenderer; + private _discardChanges = false; + public constructor(state: PanelEditorState) { super(state); + + this.addActivationHandler(() => { + return () => { + if (!this._discardChanges) { + this.commitChanges(); + } + }; + }); } public getUrlKey() { return this.state.panelId.toString(); @@ -55,23 +64,11 @@ export class PanelEditor extends SceneObjectBase { } public onDiscard = () => { - // Open question on what to preserve when going back - // Preserve time range, and variables state (that might have been changed while in panel edit) - // Preserve current panel data? (say if you just changed the time range and have new data) - this._navigateBackToDashboard(); + this._discardChanges = true; + locationService.partial({ editPanel: null }); }; - public onApply = () => { - this._commitChanges(); - this._navigateBackToDashboard(); - }; - - public onSave = () => { - this._commitChanges(); - // Open dashboard save drawer - }; - - private _commitChanges() { + public commitChanges() { const dashboard = getDashboardSceneFor(this); const sourcePanel = findVizPanelByKey(dashboard.state.body, getVizPanelKeyForPanelId(this.state.panelId)); @@ -84,26 +81,6 @@ export class PanelEditor extends SceneObjectBase { if (sourcePanel!.parent instanceof SceneGridItem) { sourcePanel!.parent.setState({ body: panelMngr.state.panel.clone() }); } - - dashboard.setState({ - isDirty: true, - }); - } - - private _navigateBackToDashboard() { - const dashboard = getDashboardSceneFor(this); - locationService.push( - getDashboardUrl({ - uid: dashboard.state.uid, - slug: dashboard.state.meta.slug, - currentQueryParams: locationService.getLocation().search, - updateQuery: { - editPanel: null, - // Clean the PanelEditor data pane tab query param - tab: null, - }, - }) - ); } } diff --git a/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx b/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx index a3f5922fc98..f3ab6279ef2 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx @@ -3,10 +3,9 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { SceneComponentProps } from '@grafana/scenes'; -import { Button, useStyles2 } from '@grafana/ui'; -import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate'; -import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbar/NavToolbarSeparator'; +import { useStyles2 } from '@grafana/ui'; +import { NavToolbarActions } from '../scene/NavToolbarActions'; import { getDashboardSceneFor } from '../utils/utils'; import { PanelEditor } from './PanelEditor'; @@ -19,7 +18,7 @@ export function PanelEditorRenderer({ model }: SceneComponentProps) return ( <> - +
{controls && (
@@ -36,29 +35,6 @@ export function PanelEditorRenderer({ model }: SceneComponentProps) ); } -function getToolbarActions(editor: PanelEditor) { - return ( - <> - - - - - - - ); -} - function getStyles(theme: GrafanaTheme2) { return { canvasContent: css({ diff --git a/public/app/features/dashboard-scene/saving/getSaveDashboardChange.test.ts b/public/app/features/dashboard-scene/saving/getSaveDashboardChange.test.ts index d443d83ba68..3c4b5577ed4 100644 --- a/public/app/features/dashboard-scene/saving/getSaveDashboardChange.test.ts +++ b/public/app/features/dashboard-scene/saving/getSaveDashboardChange.test.ts @@ -1,7 +1,9 @@ import { MultiValueVariable, sceneGraph } from '@grafana/scenes'; +import { buildPanelEditScene } from '../panel-edit/PanelEditor'; import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene'; import { transformSceneToSaveModel } from '../serialization/transformSceneToSaveModel'; +import { findVizPanelByKey } from '../utils/utils'; import { getSaveDashboardChange } from './getSaveDashboardChange'; @@ -59,15 +61,43 @@ describe('getSaveDashboardChange', () => { expect(result.hasChanges).toBe(true); expect(result.diffCount).toBe(2); }); + + describe('Saving from panel edit', () => { + it('Should commit panel edit changes', () => { + const dashboard = setup(); + const panel = findVizPanelByKey(dashboard, 'panel-1')!; + const editScene = buildPanelEditScene(panel); + + dashboard.onEnterEditMode(); + dashboard.setState({ editPanel: editScene }); + + const vizManager = editScene.state.panelRef.resolve(); + vizManager.state.panel.setState({ title: 'changed title' }); + + const result = getSaveDashboardChange(dashboard, false, true); + const panelSaveModel = result.changedSaveModel.panels![0]; + expect(panelSaveModel.title).toBe('changed title'); + }); + }); }); -function setup() { +interface ScenarioOptions { + fromPanelEdit?: boolean; +} + +function setup(options: ScenarioOptions = {}) { const dashboard = transformSaveModelToScene({ dashboard: { title: 'hello', uid: 'my-uid', schemaVersion: 30, - panels: [], + panels: [ + { + id: 1, + title: 'Panel 1', + type: 'text', + }, + ], version: 10, templating: { list: [ diff --git a/public/app/features/dashboard-scene/saving/getSaveDashboardChange.ts b/public/app/features/dashboard-scene/saving/getSaveDashboardChange.ts index 86f771a1f50..f9f9ab943cb 100644 --- a/public/app/features/dashboard-scene/saving/getSaveDashboardChange.ts +++ b/public/app/features/dashboard-scene/saving/getSaveDashboardChange.ts @@ -15,6 +15,11 @@ export function getSaveDashboardChange( saveVariables?: boolean ): DashboardChangeInfo { const initialSaveModel = dashboard.getInitialSaveModel()!; + + if (dashboard.state.editPanel) { + dashboard.state.editPanel.commitChanges(); + } + const changedSaveModel = transformSceneToSaveModel(dashboard); const hasTimeChanged = getHasTimeChanged(changedSaveModel, initialSaveModel); diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx index c3d5b25292d..8b1e01af6b7 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx @@ -36,14 +36,16 @@ NavToolbarActions.displayName = 'NavToolbarActions'; * This part is split into a separate componet to help test this */ export function ToolbarActions({ dashboard }: Props) { - const { isEditing, viewPanelScene, isDirty, uid, meta, editview } = dashboard.useState(); + const { isEditing, viewPanelScene, isDirty, uid, meta, editview, editPanel } = dashboard.useState(); const canSaveAs = contextSrv.hasEditPermissionInFolders; const toolbarActions: ToolbarAction[] = []; const buttonWithExtraMargin = useStyles2(getStyles); + const isEditingPanel = Boolean(editPanel); + const isViewingPanel = Boolean(viewPanelScene); toolbarActions.push({ group: 'icon-actions', - condition: uid && !editview && Boolean(meta.canStar), + condition: uid && !editview && Boolean(meta.canStar) && !isEditingPanel, render: () => { let desc = meta.isStarred ? t('dashboard.toolbar.unmark-favorite', 'Unmark as favorite') @@ -66,7 +68,7 @@ export function ToolbarActions({ dashboard }: Props) { toolbarActions.push({ group: 'icon-actions', - condition: uid && !editview, + condition: uid && !editview && !isEditingPanel, render: () => ( 0) { + if (dynamicDashNavActions.left.length > 0 && !isEditingPanel) { dynamicDashNavActions.left.map((action, index) => { const props = { dashboard: getDashboardSrv().getCurrent()! }; if (action.show(props)) { @@ -114,11 +116,11 @@ export function ToolbarActions({ dashboard }: Props) { toolbarActions.push({ group: 'back-button', - condition: Boolean(viewPanelScene), + condition: isViewingPanel || isEditingPanel, render: () => ( + ), + }); + toolbarActions.push({ group: 'main-buttons', condition: isEditing && (meta.canSave || canSaveAs), From 556d531c8d65d7810e71b7d22c94271a18148327 Mon Sep 17 00:00:00 2001 From: George Robinson Date: Tue, 13 Feb 2024 13:37:33 +0000 Subject: [PATCH 42/43] Alerting: Update grafana/alerting to 92f64f0 (#82373) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 76c90594320..490e4675ca9 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/google/uuid v1.6.0 // @grafana/backend-platform github.com/google/wire v0.5.0 // @grafana/backend-platform github.com/gorilla/websocket v1.5.0 // @grafana/grafana-app-platform-squad - github.com/grafana/alerting v0.0.0-20240208110638-b1d7d5f9cbf2 // @grafana/alerting-squad-backend + github.com/grafana/alerting v0.0.0-20240213130827-92f64f0f2a12 // @grafana/alerting-squad-backend github.com/grafana/cuetsy v0.1.11 // @grafana/grafana-as-code github.com/grafana/grafana-aws-sdk v0.23.1 // @grafana/aws-datasources github.com/grafana/grafana-azure-sdk-go v1.12.0 // @grafana/partner-datasources diff --git a/go.sum b/go.sum index c8e57f65457..e5d5a398556 100644 --- a/go.sum +++ b/go.sum @@ -2506,8 +2506,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gotestyourself/gotestyourself v1.3.0/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/grafana/alerting v0.0.0-20240208110638-b1d7d5f9cbf2 h1:a85edeQM7SXGcVmlQ1QAC2nE++LWS+Q4Q/lmc/jBG7k= -github.com/grafana/alerting v0.0.0-20240208110638-b1d7d5f9cbf2/go.mod h1:brTFeACal/cSZAR8XO/4LPKs7rzNfS86okl6QjSP1eY= +github.com/grafana/alerting v0.0.0-20240213130827-92f64f0f2a12 h1:QepaY7wUP3U1hFiU1Lnv+tymnovzK21KQ/evMDpYsEw= +github.com/grafana/alerting v0.0.0-20240213130827-92f64f0f2a12/go.mod h1:brTFeACal/cSZAR8XO/4LPKs7rzNfS86okl6QjSP1eY= github.com/grafana/codejen v0.0.3 h1:tAWxoTUuhgmEqxJPOLtJoxlPBbMULFwKFOcRsPRPXDw= github.com/grafana/codejen v0.0.3/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s= github.com/grafana/cue v0.0.0-20230926092038-971951014e3f h1:TmYAMnqg3d5KYEAaT6PtTguL2GjLfvr6wnAX8Azw6tQ= From 99fa0645769d534d846fee454b8792a677fb5f8b Mon Sep 17 00:00:00 2001 From: Alexander Weaver Date: Tue, 13 Feb 2024 08:29:03 -0600 Subject: [PATCH 43/43] Alerting: Emit warning when creating or updating unusually large groups (#82279) * Add config for limit of rules per rule group * Warn when editing big groups through normal API * Warn on prov api writes for groups * Wire up comp root, tests * Also add warning to state manager warm * Drop unnecessary conversion --- conf/defaults.ini | 4 ++++ conf/sample.ini | 4 ++++ .../ngalert/api/api_provisioning_test.go | 2 +- pkg/services/ngalert/api/api_ruler.go | 16 ++++++++++++++++ pkg/services/ngalert/ngalert.go | 4 +++- .../ngalert/provisioning/alert_rules.go | 19 +++++++++++++++++++ pkg/services/ngalert/state/manager.go | 18 ++++++++++++++++++ pkg/services/provisioning/provisioning.go | 1 + pkg/setting/setting_unified_alerting.go | 4 ++++ 9 files changed, 70 insertions(+), 2 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index 8bcb30a11e5..ad7b944a02d 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -1111,6 +1111,10 @@ global_file = 1000 # global limit of correlations global_correlations = -1 +# Limit of the number of alert rules per rule group. +# This is not strictly enforced yet, but will be enforced over time. +alerting_rule_group_rules = 100 + #################################### Unified Alerting #################### [unified_alerting] # Enable the Unified Alerting sub-system and interface. When enabled we'll migrate all of your alert rules and notification channels to the new system. New alert rules will be created and your notification channels will be converted into an Alertmanager configuration. Previous data is preserved to enable backwards compatibility but new data is removed when switching. When this configuration section and flag are not defined, the state is defined at runtime. See the documentation for more details. diff --git a/conf/sample.ini b/conf/sample.ini index e938b40ff58..259c110d8ed 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -1041,6 +1041,10 @@ # global limit of correlations ; global_correlations = -1 +# Limit of the number of alert rules per rule group. +# This is not strictly enforced yet, but will be enforced over time. +;alerting_rule_group_rules = 100 + #################################### Unified Alerting #################### [unified_alerting] #Enable the Unified Alerting sub-system and interface. When enabled we'll migrate all of your alert rules and notification channels to the new system. New alert rules will be created and your notification channels will be converted into an Alertmanager configuration. Previous data is preserved to enable backwards compatibility but new data is removed.``` diff --git a/pkg/services/ngalert/api/api_provisioning_test.go b/pkg/services/ngalert/api/api_provisioning_test.go index 1fc0fb12bb2..c11f76905a9 100644 --- a/pkg/services/ngalert/api/api_provisioning_test.go +++ b/pkg/services/ngalert/api/api_provisioning_test.go @@ -1632,7 +1632,7 @@ func createProvisioningSrvSutFromEnv(t *testing.T, env *testEnvironment) Provisi contactPointService: provisioning.NewContactPointService(env.configs, env.secrets, env.prov, env.xact, receiverSvc, env.log), templates: provisioning.NewTemplateService(env.configs, env.prov, env.xact, env.log), muteTimings: provisioning.NewMuteTimingService(env.configs, env.prov, env.xact, env.log), - alertRules: provisioning.NewAlertRuleService(env.store, env.prov, env.dashboardService, env.quotas, env.xact, 60, 10, env.log), + alertRules: provisioning.NewAlertRuleService(env.store, env.prov, env.dashboardService, env.quotas, env.xact, 60, 10, 100, env.log), } } diff --git a/pkg/services/ngalert/api/api_ruler.go b/pkg/services/ngalert/api/api_ruler.go index c68354b2963..f9d7a49ac16 100644 --- a/pkg/services/ngalert/api/api_ruler.go +++ b/pkg/services/ngalert/api/api_ruler.go @@ -251,6 +251,10 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *contextmodel.ReqContext, ruleGro return toNamespaceErrorResponse(err) } + if err := srv.checkGroupLimits(ruleGroupConfig); err != nil { + return ErrResp(http.StatusBadRequest, err, "") + } + rules, err := validateRuleGroup(&ruleGroupConfig, c.SignedInUser.GetOrgID(), namespace, srv.cfg) if err != nil { return ErrResp(http.StatusBadRequest, err, "") @@ -265,6 +269,18 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *contextmodel.ReqContext, ruleGro return srv.updateAlertRulesInGroup(c, groupKey, rules) } +func (srv RulerSrv) checkGroupLimits(group apimodels.PostableRuleGroupConfig) error { + if srv.cfg.RulesPerRuleGroupLimit > 0 && int64(len(group.Rules)) > srv.cfg.RulesPerRuleGroupLimit { + srv.log.Warn("Large rule group was edited. Large groups are discouraged and may be rejected in the future.", + "limit", srv.cfg.RulesPerRuleGroupLimit, + "actual", len(group.Rules), + "group", group.Name, + ) + } + + return nil +} + // updateAlertRulesInGroup calculates changes (rules to add,update,delete), verifies that the user is authorized to do the calculated changes and updates database. // All operations are performed in a single transaction func (srv RulerSrv) updateAlertRulesInGroup(c *contextmodel.ReqContext, groupKey ngmodels.AlertRuleGroupKey, rules []*ngmodels.AlertRuleWithOptionals) response.Response { diff --git a/pkg/services/ngalert/ngalert.go b/pkg/services/ngalert/ngalert.go index d75f5d91960..8ea504f0001 100644 --- a/pkg/services/ngalert/ngalert.go +++ b/pkg/services/ngalert/ngalert.go @@ -301,6 +301,7 @@ func (ng *AlertNG) init() error { DoNotSaveNormalState: ng.FeatureToggles.IsEnabledGlobally(featuremgmt.FlagAlertingNoNormalState), ApplyNoDataAndErrorToAllStates: ng.FeatureToggles.IsEnabledGlobally(featuremgmt.FlagAlertingNoDataErrorExecution), MaxStateSaveConcurrency: ng.Cfg.UnifiedAlerting.MaxStateSaveConcurrency, + RulesPerRuleGroupLimit: ng.Cfg.UnifiedAlerting.RulesPerRuleGroupLimit, Tracer: ng.tracer, Log: log.New("ngalert.state.manager"), } @@ -330,7 +331,8 @@ func (ng *AlertNG) init() error { muteTimingService := provisioning.NewMuteTimingService(ng.store, ng.store, ng.store, ng.Log) alertRuleService := provisioning.NewAlertRuleService(ng.store, ng.store, ng.dashboardService, ng.QuotaService, ng.store, int64(ng.Cfg.UnifiedAlerting.DefaultRuleEvaluationInterval.Seconds()), - int64(ng.Cfg.UnifiedAlerting.BaseInterval.Seconds()), ng.Log) + int64(ng.Cfg.UnifiedAlerting.BaseInterval.Seconds()), + ng.Cfg.UnifiedAlerting.RulesPerRuleGroupLimit, ng.Log) ng.api = &api.API{ Cfg: ng.Cfg, diff --git a/pkg/services/ngalert/provisioning/alert_rules.go b/pkg/services/ngalert/provisioning/alert_rules.go index 043f7d8d989..c83eee732ab 100644 --- a/pkg/services/ngalert/provisioning/alert_rules.go +++ b/pkg/services/ngalert/provisioning/alert_rules.go @@ -17,6 +17,7 @@ import ( type AlertRuleService struct { defaultIntervalSeconds int64 baseIntervalSeconds int64 + rulesPerRuleGroupLimit int64 ruleStore RuleStore provenanceStore ProvisioningStore dashboardService dashboards.DashboardService @@ -32,10 +33,12 @@ func NewAlertRuleService(ruleStore RuleStore, xact TransactionManager, defaultIntervalSeconds int64, baseIntervalSeconds int64, + rulesPerRuleGroupLimit int64, log log.Logger) *AlertRuleService { return &AlertRuleService{ defaultIntervalSeconds: defaultIntervalSeconds, baseIntervalSeconds: baseIntervalSeconds, + rulesPerRuleGroupLimit: rulesPerRuleGroupLimit, ruleStore: ruleStore, provenanceStore: provenanceStore, dashboardService: dashboardService, @@ -248,6 +251,10 @@ func (service *AlertRuleService) ReplaceRuleGroup(ctx context.Context, orgID int } } + if err := service.checkGroupLimits(group); err != nil { + return fmt.Errorf("write rejected due to exceeded limits: %w", err) + } + key := models.AlertRuleGroupKey{ OrgID: orgID, NamespaceUID: group.FolderUID, @@ -533,3 +540,15 @@ func withoutNilAlertRules(ptrs []*models.AlertRule) []models.AlertRule { } return result } + +func (service *AlertRuleService) checkGroupLimits(group models.AlertRuleGroup) error { + if service.rulesPerRuleGroupLimit > 0 && int64(len(group.Rules)) > service.rulesPerRuleGroupLimit { + service.log.Warn("Large rule group was edited. Large groups are discouraged and may be rejected in the future.", + "limit", service.rulesPerRuleGroupLimit, + "actual", len(group.Rules), + "group", group.Title, + ) + } + + return nil +} diff --git a/pkg/services/ngalert/state/manager.go b/pkg/services/ngalert/state/manager.go index 2f8eb2cf1bc..4b0f11e397e 100644 --- a/pkg/services/ngalert/state/manager.go +++ b/pkg/services/ngalert/state/manager.go @@ -50,6 +50,7 @@ type Manager struct { doNotSaveNormalState bool applyNoDataAndErrorToAllStates bool + rulesPerRuleGroupLimit int64 persister StatePersister } @@ -68,6 +69,7 @@ type ManagerCfg struct { // ApplyNoDataAndErrorToAllStates makes state manager to apply exceptional results (NoData and Error) // to all states when corresponding execution in the rule definition is set to either `Alerting` or `OK` ApplyNoDataAndErrorToAllStates bool + RulesPerRuleGroupLimit int64 Tracer tracing.Tracer Log log.Logger @@ -92,6 +94,7 @@ func NewManager(cfg ManagerCfg, statePersister StatePersister) *Manager { externalURL: cfg.ExternalURL, doNotSaveNormalState: cfg.DoNotSaveNormalState, applyNoDataAndErrorToAllStates: cfg.ApplyNoDataAndErrorToAllStates, + rulesPerRuleGroupLimit: cfg.RulesPerRuleGroupLimit, persister: statePersister, tracer: cfg.Tracer, } @@ -134,8 +137,23 @@ func (st *Manager) Warm(ctx context.Context, rulesReader RuleReader) { } ruleByUID := make(map[string]*ngModels.AlertRule, len(alertRules)) + groupSizes := make(map[string]int64) for _, rule := range alertRules { ruleByUID[rule.UID] = rule + groupSizes[rule.RuleGroup] += 1 + } + + // Emit a warning if we detect a large group. + // We will not enforce this here, but it's convenient to emit the warning here as we load up all the rules. + for name, size := range groupSizes { + if st.rulesPerRuleGroupLimit > 0 && size > st.rulesPerRuleGroupLimit { + st.log.Warn( + "Large rule group was loaded. Large groups are discouraged and changes to them may be disallowed in the future.", + "limit", st.rulesPerRuleGroupLimit, + "actual", size, + "group", name, + ) + } } orgStates := make(map[string]*ruleStates, len(ruleByUID)) diff --git a/pkg/services/provisioning/provisioning.go b/pkg/services/provisioning/provisioning.go index 2f35b9d60e9..91e5669208b 100644 --- a/pkg/services/provisioning/provisioning.go +++ b/pkg/services/provisioning/provisioning.go @@ -280,6 +280,7 @@ func (ps *ProvisioningServiceImpl) ProvisionAlerting(ctx context.Context) error ps.SQLStore, int64(ps.Cfg.UnifiedAlerting.DefaultRuleEvaluationInterval.Seconds()), int64(ps.Cfg.UnifiedAlerting.BaseInterval.Seconds()), + ps.Cfg.UnifiedAlerting.RulesPerRuleGroupLimit, ps.log) receiverSvc := alertingNotifier.NewReceiverService(ps.ac, &st, st, ps.secretService, ps.SQLStore, ps.log) contactPointService := provisioning.NewContactPointService(&st, ps.secretService, diff --git a/pkg/setting/setting_unified_alerting.go b/pkg/setting/setting_unified_alerting.go index b42f0869fee..0b09df67c93 100644 --- a/pkg/setting/setting_unified_alerting.go +++ b/pkg/setting/setting_unified_alerting.go @@ -101,6 +101,7 @@ type UnifiedAlertingSettings struct { // MaxStateSaveConcurrency controls the number of goroutines (per rule) that can save alert state in parallel. MaxStateSaveConcurrency int StatePeriodicSaveInterval time.Duration + RulesPerRuleGroupLimit int64 } // RemoteAlertmanagerSettings contains the configuration needed @@ -352,6 +353,9 @@ func (cfg *Cfg) ReadUnifiedAlertingSettings(iniFile *ini.File) error { uaCfg.DefaultRuleEvaluationInterval = uaMinInterval } + quotas := iniFile.Section("quota") + uaCfg.RulesPerRuleGroupLimit = quotas.Key("alerting_rule_group_rules").MustInt64(100) + remoteAlertmanager := iniFile.Section("remote.alertmanager") uaCfgRemoteAM := RemoteAlertmanagerSettings{ Enable: remoteAlertmanager.Key("enabled").MustBool(false),