mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Pass yaml as a query param in export request (#62751)
* Set YAML as default value for exporting alert rules * use YAML format for rule list export Co-authored-by: Sonia Aguilar <33540275+soniaAguilarPeiron@users.noreply.github.com> * lint * Add new format query param to swagger+docs * Fix broken test --------- Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> Co-authored-by: Matt Jacobson <matthew.jacobson@grafana.com>
This commit is contained in:
parent
99a16d27c1
commit
753c84f825
@ -244,10 +244,11 @@ GET /api/v1/provisioning/alert-rules/{UID}/export
|
||||
|
||||
#### 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. |
|
||||
| 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
|
||||
|
||||
@ -322,11 +323,12 @@ GET /api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}/export
|
||||
|
||||
#### 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. |
|
||||
| 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
|
||||
|
||||
@ -381,9 +383,10 @@ 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. |
|
||||
| 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
|
||||
|
||||
|
@ -428,12 +428,22 @@ func determineProvenance(ctx *contextmodel.ReqContext) alerting_models.Provenanc
|
||||
}
|
||||
|
||||
func exportResponse(c *contextmodel.ReqContext, body any) response.Response {
|
||||
format := "json"
|
||||
var format = "yaml"
|
||||
|
||||
acceptHeader := c.Req.Header.Get("Accept")
|
||||
if strings.Contains(acceptHeader, "yaml") && !strings.Contains(acceptHeader, "json") {
|
||||
if strings.Contains(acceptHeader, "yaml") {
|
||||
format = "yaml"
|
||||
}
|
||||
|
||||
if strings.Contains(acceptHeader, "json") {
|
||||
format = "json"
|
||||
}
|
||||
|
||||
queryFormat := c.Query("format")
|
||||
if queryFormat == "yaml" || queryFormat == "json" {
|
||||
format = queryFormat
|
||||
}
|
||||
|
||||
download := c.QueryBoolWithDefault("download", false)
|
||||
if download {
|
||||
r := response.JSONDownload
|
||||
|
@ -410,6 +410,34 @@ func TestProvisioningApi(t *testing.T) {
|
||||
require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type"))
|
||||
})
|
||||
|
||||
t.Run("query format contains yaml, GET returns text yaml", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSut(t)
|
||||
rc := createTestRequestCtx()
|
||||
insertRule(t, sut, createTestAlertRule("rule", 1))
|
||||
|
||||
rc.Context.Req.Form.Set("format", "yaml")
|
||||
|
||||
response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group")
|
||||
response.WriteTo(&rc)
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type"))
|
||||
})
|
||||
|
||||
t.Run("query format contains unknown value, GET returns text yaml", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSut(t)
|
||||
rc := createTestRequestCtx()
|
||||
insertRule(t, sut, createTestAlertRule("rule", 1))
|
||||
|
||||
rc.Context.Req.Form.Set("format", "foo")
|
||||
|
||||
response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group")
|
||||
response.WriteTo(&rc)
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type"))
|
||||
})
|
||||
|
||||
t.Run("accept header contains json, GET returns json", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSut(t)
|
||||
rc := createTestRequestCtx()
|
||||
@ -474,12 +502,31 @@ func TestProvisioningApi(t *testing.T) {
|
||||
require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition"))
|
||||
})
|
||||
|
||||
t.Run("yaml body content is the default", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSut(t)
|
||||
rc := createTestRequestCtx()
|
||||
insertRule(t, sut, createTestAlertRule("rule1", 1))
|
||||
insertRule(t, sut, createTestAlertRule("rule2", 1))
|
||||
|
||||
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: my-cool-group\n folder" +
|
||||
": Folder Title\n interval: 1m\n rules:\n - uid: rule1\n title: rule1\n" +
|
||||
" condition: A\n data:\n - refId: A\n datasourceUid" +
|
||||
": \"\"\n model:\n conditions:\n - evaluator:\n" +
|
||||
" params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n - uid: rule2\n title: rule2\n condition: A\n data:\n - refId: A\n datasourceUid: \"\"\n model:\n conditions:\n - evaluator:\n params:\n - 3\n type: gt\n operator:\n type: and\n query:\n params:\n - A\n reducer:\n type: last\n type: query\n datasource:\n type: __expr__\n uid: __expr__\n expression: 1==0\n intervalMs: 1000\n maxDataPoints: 43200\n refId: A\n type: math\n noDataState: OK\n execErrState: OK\n for: 0s\n isPaused: false\n"
|
||||
|
||||
response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group")
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, expectedResponse, string(response.Body()))
|
||||
})
|
||||
|
||||
t.Run("json body content is as expected", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSut(t)
|
||||
rc := createTestRequestCtx()
|
||||
insertRule(t, sut, createTestAlertRule("rule1", 1))
|
||||
insertRule(t, sut, createTestAlertRule("rule2", 1))
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false},{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group")
|
||||
@ -613,6 +660,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}`
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
response := sut.RouteGetAlertRuleExport(&rc, "rule1")
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
@ -729,6 +777,7 @@ func TestProvisioningApi(t *testing.T) {
|
||||
insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupb"))
|
||||
insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb"))
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]},{"orgId":1,"name":"groupb","folder":"Folder Title2","interval":"1m","rules":[{"uid":"rule3","title":"rule3","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}`
|
||||
|
||||
response := sut.RouteGetAlertRulesExport(&rc)
|
||||
|
@ -363,6 +363,10 @@
|
||||
"external"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"numExternalAlertmanagers": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@ -3290,6 +3294,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"URL": {
|
||||
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
|
||||
"properties": {
|
||||
"ForceQuery": {
|
||||
"type": "boolean"
|
||||
@ -3325,7 +3330,7 @@
|
||||
"$ref": "#/definitions/Userinfo"
|
||||
}
|
||||
},
|
||||
"title": "URL is a custom URL type that allows validation at configuration load time.",
|
||||
"title": "A URL represents a parsed URL (technically, a URI reference).",
|
||||
"type": "object"
|
||||
},
|
||||
"Userinfo": {
|
||||
@ -3502,7 +3507,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"alertGroup": {
|
||||
"description": "AlertGroup alert group",
|
||||
"properties": {
|
||||
"alerts": {
|
||||
"description": "alerts",
|
||||
@ -3526,6 +3530,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"alertGroups": {
|
||||
"description": "AlertGroups alert groups",
|
||||
"items": {
|
||||
"$ref": "#/definitions/alertGroup"
|
||||
},
|
||||
@ -3630,7 +3635,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableAlert": {
|
||||
"description": "GettableAlert gettable alert",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"$ref": "#/definitions/labelSet"
|
||||
@ -3686,6 +3690,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableAlerts": {
|
||||
"description": "GettableAlerts gettable alerts",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gettableAlert"
|
||||
},
|
||||
@ -3740,14 +3745,12 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableSilences": {
|
||||
"description": "GettableSilences gettable silences",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gettableSilence"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"integration": {
|
||||
"description": "Integration integration",
|
||||
"properties": {
|
||||
"lastNotifyAttempt": {
|
||||
"description": "A timestamp indicating the last attempt to deliver a notification regardless of the outcome.\nFormat: date-time",
|
||||
@ -4113,6 +4116,13 @@
|
||||
"in": "query",
|
||||
"name": "download",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -4244,6 +4254,13 @@
|
||||
"in": "query",
|
||||
"name": "download",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
@ -4493,6 +4510,13 @@
|
||||
"in": "query",
|
||||
"name": "download",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
|
@ -249,6 +249,12 @@ type ExportQueryParams struct {
|
||||
// required: false
|
||||
// default: false
|
||||
Download bool `json:"download"`
|
||||
|
||||
// Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.
|
||||
// in: query
|
||||
// required: false
|
||||
// default: yaml
|
||||
Format string `json:"format"`
|
||||
}
|
||||
|
||||
// swagger:model
|
||||
|
@ -363,6 +363,10 @@
|
||||
"external"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"numExternalAlertmanagers": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@ -3290,6 +3294,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"URL": {
|
||||
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
|
||||
"properties": {
|
||||
"ForceQuery": {
|
||||
"type": "boolean"
|
||||
@ -3325,7 +3330,7 @@
|
||||
"$ref": "#/definitions/Userinfo"
|
||||
}
|
||||
},
|
||||
"title": "URL is a custom URL type that allows validation at configuration load time.",
|
||||
"title": "A URL represents a parsed URL (technically, a URI reference).",
|
||||
"type": "object"
|
||||
},
|
||||
"Userinfo": {
|
||||
@ -3502,6 +3507,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"alertGroup": {
|
||||
"description": "AlertGroup alert group",
|
||||
"properties": {
|
||||
"alerts": {
|
||||
"description": "alerts",
|
||||
@ -3525,7 +3531,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"alertGroups": {
|
||||
"description": "AlertGroups alert groups",
|
||||
"items": {
|
||||
"$ref": "#/definitions/alertGroup"
|
||||
},
|
||||
@ -3630,6 +3635,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableAlert": {
|
||||
"description": "GettableAlert gettable alert",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"$ref": "#/definitions/labelSet"
|
||||
@ -3691,6 +3697,7 @@
|
||||
"type": "array"
|
||||
},
|
||||
"gettableSilence": {
|
||||
"description": "GettableSilence gettable silence",
|
||||
"properties": {
|
||||
"comment": {
|
||||
"description": "comment",
|
||||
@ -3927,7 +3934,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"receiver": {
|
||||
"description": "Receiver receiver",
|
||||
"properties": {
|
||||
"active": {
|
||||
"description": "active",
|
||||
@ -5784,6 +5790,13 @@
|
||||
"in": "query",
|
||||
"name": "download",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -5915,6 +5928,13 @@
|
||||
"in": "query",
|
||||
"name": "download",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
@ -6164,6 +6184,13 @@
|
||||
"in": "query",
|
||||
"name": "download",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"in": "query",
|
||||
"name": "format",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
|
@ -1761,6 +1761,13 @@
|
||||
"description": "Whether to initiate a download of the file or not.",
|
||||
"name": "download",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"name": "format",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -1901,6 +1908,13 @@
|
||||
"description": "Whether to initiate a download of the file or not.",
|
||||
"name": "download",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"name": "format",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -2157,6 +2171,13 @@
|
||||
"description": "Whether to initiate a download of the file or not.",
|
||||
"name": "download",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"default": "yaml",
|
||||
"description": "Format of the downloaded file, either yaml or json. Accept header can also be used, but the query parameter will take precedence.",
|
||||
"name": "format",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -2975,6 +2996,10 @@
|
||||
"internal",
|
||||
"external"
|
||||
]
|
||||
},
|
||||
"numExternalAlertmanagers": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -5905,8 +5930,9 @@
|
||||
}
|
||||
},
|
||||
"URL": {
|
||||
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
|
||||
"type": "object",
|
||||
"title": "URL is a custom URL type that allows validation at configuration load time.",
|
||||
"title": "A URL represents a parsed URL (technically, a URI reference).",
|
||||
"properties": {
|
||||
"ForceQuery": {
|
||||
"type": "boolean"
|
||||
@ -6117,6 +6143,7 @@
|
||||
}
|
||||
},
|
||||
"alertGroup": {
|
||||
"description": "AlertGroup alert group",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"alerts",
|
||||
@ -6141,7 +6168,6 @@
|
||||
"$ref": "#/definitions/alertGroup"
|
||||
},
|
||||
"alertGroups": {
|
||||
"description": "AlertGroups alert groups",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/alertGroup"
|
||||
@ -6247,6 +6273,7 @@
|
||||
}
|
||||
},
|
||||
"gettableAlert": {
|
||||
"description": "GettableAlert gettable alert",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"labels",
|
||||
@ -6310,6 +6337,7 @@
|
||||
"$ref": "#/definitions/gettableAlerts"
|
||||
},
|
||||
"gettableSilence": {
|
||||
"description": "GettableSilence gettable silence",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"comment",
|
||||
@ -6550,7 +6578,6 @@
|
||||
"$ref": "#/definitions/postableSilence"
|
||||
},
|
||||
"receiver": {
|
||||
"description": "Receiver receiver",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"active",
|
||||
|
@ -5,7 +5,7 @@ import { useAsyncFn, useInterval } from 'react-use';
|
||||
|
||||
import { GrafanaTheme2, urlUtil } from '@grafana/data';
|
||||
import { Stack } from '@grafana/experimental';
|
||||
import { BackendSrvRequest, getBackendSrv, logInfo } from '@grafana/runtime';
|
||||
import { logInfo } from '@grafana/runtime';
|
||||
import { Button, LinkButton, useStyles2, withErrorBoundary } from '@grafana/ui';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { useDispatch } from 'app/types';
|
||||
@ -33,20 +33,7 @@ const VIEWS = {
|
||||
state: RuleListStateView,
|
||||
};
|
||||
|
||||
const onExport = async () => {
|
||||
const exportURL = `/api/v1/provisioning/alert-rules/export?download=true`;
|
||||
const options: BackendSrvRequest = {
|
||||
url: exportURL,
|
||||
headers: { Accept: 'yaml' },
|
||||
responseType: 'blob',
|
||||
};
|
||||
const blob = await getBackendSrv().get(exportURL, undefined, undefined, options);
|
||||
const fileUrl = window.URL.createObjectURL(blob);
|
||||
const downloadLink = document.createElement('a');
|
||||
downloadLink.href = fileUrl;
|
||||
downloadLink.download = 'export.yaml';
|
||||
downloadLink.click();
|
||||
};
|
||||
const onExport = () => window.open('/api/v1/provisioning/alert-rules/export?download=true&format=yaml');
|
||||
|
||||
const RuleList = withErrorBoundary(
|
||||
() => {
|
||||
|
Loading…
Reference in New Issue
Block a user