Expressions: Fixes the issue showing expressions editor (#62510)

* Use suggested value for uid

* update the snapshot

* use __expr__

* replace all -100 with __expr__

* update snapshot

* more changes

* revert redundant change

* Use expr.DatasourceUID where it's possible

* generate files
This commit is contained in:
ismail simsek 2023-01-31 18:50:10 +01:00 committed by GitHub
parent fdb1a47ca2
commit 91221bc436
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 259 additions and 242 deletions

View File

@ -23,7 +23,7 @@ apiVersion: 1
# # evaluation - should be obtained via the API
# data:
# - refId: A
# datasourceUid: "-100"
# datasourceUid: "__expr__"
# model:
# conditions:
# - evaluator:
@ -40,7 +40,7 @@ apiVersion: 1
# type: query
# datasource:
# type: __expr__
# uid: "-100"
# uid: "__expr__"
# expression: 1==0
# intervalMs: 1000
# maxDataPoints: 43200

View File

@ -69,7 +69,7 @@ groups:
# evaluation - should be obtained trough the API
data:
- refId: A
datasourceUid: '-100'
datasourceUid: '__expr__'
model:
conditions:
- evaluator:
@ -86,7 +86,7 @@ groups:
type: query
datasource:
type: __expr__
uid: '-100'
uid: '__expr__'
expression: 1==0
intervalMs: 1000
maxDataPoints: 43200

View File

@ -282,7 +282,7 @@ resource "grafana_rule_group" "my_rule_group" {
// 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 = "-100"
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 = <<EOT
@ -298,7 +298,7 @@ EOT
// Now, let's use a math expression as our threshold.
// We want to alert when the value of stage "B" above exceeds 70.
data {
datasource_uid = "-100"
datasource_uid = "__expr__"
ref_id = "C"
relative_time_range {
from = 0

View File

@ -992,14 +992,14 @@ Status: Accepted
**Properties**
| Name | Type | Go type | Required | Default | Description | Example |
| --------------------------------------------------------- | ----------------------------------------- | ------------------- | :------: | ------- | -------------------------------------------------------------------------------------------------- | ------- |
| datasourceUid | string | `string` | | | Grafana data source unique identifier; it should be '-100' 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. |
| 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` | | | | |
| refId | string | `string` | | | RefID is the unique identifier of the query, set by the frontend call. | |
| relativeTimeRange | [RelativeTimeRange](#relative-time-range) | `RelativeTimeRange` | | | | |
### <span id="alert-query-export"></span> AlertQueryExport
@ -1174,23 +1174,23 @@ Status: Accepted
**Properties**
| 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":"-100","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` | | | | |
| 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` | | | | |
| 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` | | | | |
| 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` | | | | |
### <span id="provisioned-alert-rules"></span> ProvisionedAlertRules

View File

@ -2,30 +2,30 @@ import { lastValueFrom, merge, Observable, of } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import {
DataSourceApi,
DataFrame,
dataFrameToJSON,
DataQuery,
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
DataQuery,
DataSourceJsonData,
ScopedVars,
makeClassES5Compatible,
DataFrame,
parseLiveChannelAddress,
getDataSourceRef,
DataSourceRef,
dataFrameToJSON,
getDataSourceRef,
makeClassES5Compatible,
parseLiveChannelAddress,
ScopedVars,
} from '@grafana/data';
import { config } from '../config';
import {
BackendSrvRequest,
FetchResponse,
getBackendSrv,
getDataSourceSrv,
getGrafanaLiveSrv,
StreamingFrameOptions,
StreamingFrameAction,
BackendSrvRequest,
FetchResponse,
StreamingFrameOptions,
} from '../services';
import { BackendDataSourceResponse, toDataQueryResponse } from './queryResponse';

View File

@ -8,6 +8,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -737,7 +738,7 @@ func insertTestRule(t *testing.T, sqlStore db.DB, foderOrgID int64, folderUID st
Data: []alertQuery{
{
RefID: "A",
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"

View File

@ -11,6 +11,7 @@ import (
alertingModels "github.com/grafana/alerting/alerting/models"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/expr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -571,7 +572,7 @@ func withClassicConditionSingleQuery() func(r *ngmodels.AlertRule) {
RefID: "B",
QueryType: "",
RelativeTimeRange: ngmodels.RelativeTimeRange{From: ngmodels.Duration(0), To: ngmodels.Duration(0)},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(fmt.Sprintf(classicConditionsModel, "A", "B")),
},
}
@ -600,21 +601,21 @@ func withExpressionsMultiQuery() func(r *ngmodels.AlertRule) {
RefID: "C",
QueryType: "",
RelativeTimeRange: ngmodels.RelativeTimeRange{From: ngmodels.Duration(0), To: ngmodels.Duration(0)},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(fmt.Sprintf(reduceLastExpressionModel, "A", "C")),
},
{
RefID: "D",
QueryType: "",
RelativeTimeRange: ngmodels.RelativeTimeRange{From: ngmodels.Duration(0), To: ngmodels.Duration(0)},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(fmt.Sprintf(reduceLastExpressionModel, "B", "D")),
},
{
RefID: "E",
QueryType: "",
RelativeTimeRange: ngmodels.RelativeTimeRange{From: ngmodels.Duration(0), To: ngmodels.Duration(0)},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(fmt.Sprintf(mathExpressionModel, "A", "B", "E")),
},
}

View File

@ -38,7 +38,7 @@ const classicConditionsModel = `
}],
"datasource": {
"type": "__expr__",
"uid": "-100"
"uid": "__expr__"
},
"hide": false,
"intervalMs": 1000,

View File

@ -480,7 +480,7 @@ func TestProvisioningApi(t *testing.T) {
insertRule(t, sut, createTestAlertRule("rule1", 1))
insertRule(t, sut, createTestAlertRule("rule2", 1))
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":"-100"},"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":"-100"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}`
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")
@ -495,7 +495,11 @@ func TestProvisioningApi(t *testing.T) {
insertRule(t, sut, createTestAlertRule("rule2", 1))
rc.Context.Req.Header.Add("Accept", "application/yaml")
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: \"-100\"\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: \"-100\"\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"
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")
@ -607,7 +611,7 @@ func TestProvisioningApi(t *testing.T) {
rc := createTestRequestCtx()
insertRule(t, sut, createTestAlertRule("rule1", 1))
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":"-100"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}`
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}]}]}`
response := sut.RouteGetAlertRuleExport(&rc, "rule1")
@ -621,7 +625,7 @@ func TestProvisioningApi(t *testing.T) {
insertRule(t, sut, createTestAlertRule("rule1", 1))
rc.Context.Req.Header.Add("Accept", "application/yaml")
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: \"-100\"\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"
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"
response := sut.RouteGetAlertRuleExport(&rc, "rule1")
@ -725,7 +729,7 @@ func TestProvisioningApi(t *testing.T) {
insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupb"))
insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb"))
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":"-100"},"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":"-100"},"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":"-100"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}`
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)
@ -741,7 +745,7 @@ func TestProvisioningApi(t *testing.T) {
insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb"))
rc.Context.Req.Header.Add("Accept", "application/yaml")
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: groupa\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: \"-100\"\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 - orgId: 1\n name: groupb\n folder: Folder Title\n interval: 1m\n rules:\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: \"-100\"\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 - orgId: 1\n name: groupb\n folder: Folder Title2\n interval: 1m\n rules:\n - uid: rule3\n title: rule3\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: \"-100\"\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"
expectedResponse := "apiVersion: 1\ngroups:\n - orgId: 1\n name: groupa\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 - orgId: 1\n name: groupb\n folder: Folder Title\n interval: 1m\n rules:\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 - orgId: 1\n name: groupb\n folder: Folder Title2\n interval: 1m\n rules:\n - uid: rule3\n title: rule3\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.RouteGetAlertRulesExport(&rc)
@ -1034,7 +1038,7 @@ var testModel = `
],
"datasource": {
"type": "__expr__",
"uid": "-100"
"uid": "__expr__"
},
"expression": "1==0",
"intervalMs": 1000,

View File

@ -236,7 +236,9 @@ func (api *API) authorize(method, path string) web.Handler {
// authorizeDatasourceAccessForRule checks that user has access to all data sources declared by the rule
func authorizeDatasourceAccessForRule(rule *ngmodels.AlertRule, evaluator func(evaluator ac.Evaluator) bool) bool {
for _, query := range rule.Data {
if query.QueryType == expr.DatasourceType || query.DatasourceUID == expr.OldDatasourceUID {
if query.QueryType == expr.DatasourceType || query.DatasourceUID == expr.DatasourceUID || query.
DatasourceUID == expr.
OldDatasourceUID {
continue
}
if !evaluator(ac.EvalPermission(datasources.ActionQuery, datasources.ScopeProvider.GetResourceScopeUID(query.DatasourceUID))) {

View File

@ -401,7 +401,7 @@ func TestCheckDatasourcePermissionsForRule(t *testing.T) {
expressionByType := models.GenerateAlertQuery()
expressionByType.QueryType = expr.DatasourceType
expressionByUID := models.GenerateAlertQuery()
expressionByUID.DatasourceUID = expr.OldDatasourceUID
expressionByUID.DatasourceUID = expr.DatasourceUID
var data []models.AlertQuery
var scopes []string

View File

@ -32,7 +32,7 @@
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "query",
"hide": false,
@ -50,7 +50,7 @@
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$reduced > 10",
"hide": false,
@ -95,7 +95,7 @@
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$A",
"intervalMs": 2000,
@ -112,4 +112,4 @@
}
}
]
}
}

View File

@ -39,7 +39,7 @@
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "query",
"hide": false,
@ -57,7 +57,7 @@
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$reduced > 10",
"hide": false,
@ -102,7 +102,7 @@
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$A",
"intervalMs": 2000,
@ -119,4 +119,4 @@
}
}
]
}
}

View File

@ -98,7 +98,7 @@ content-type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "query",
"hide": false,
@ -116,7 +116,7 @@ content-type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$reduced > 10",
"hide": false,
@ -184,7 +184,7 @@ content-type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "query",
"hide": false,
@ -202,7 +202,7 @@ content-type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$reduced > 42",
"hide": false,
@ -283,7 +283,7 @@ Content-Type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "query",
"hide": false,
@ -301,7 +301,7 @@ Content-Type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$reduced > 42",
"hide": false,
@ -317,4 +317,4 @@ Content-Type: application/json
}
}
]
}
}

View File

@ -9,7 +9,7 @@
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"type": "math",
"expression": "2 + 2 > 1"
@ -18,4 +18,4 @@
],
"now": "2021-03-11T14:50:42.218+02:00"
}
}
}

View File

@ -15,7 +15,7 @@ content-type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"type":"math",
"expression":"1 < 2"
@ -56,7 +56,7 @@ content-type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "$A",
"intervalMs": 2000,
@ -113,7 +113,7 @@ content-type: application/json
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"type":"math",
"expression":"1 < 2"
@ -121,7 +121,7 @@ content-type: application/json
}
]
}
}}
}
### grafana recipient - lotex payload
POST http://admin:admin@localhost:3000/api/v1/rule/test/{{grafanaRecipient}}
@ -129,4 +129,4 @@ content-type: application/json
{
"expr": "rate({cluster=\"us-central1\", job=\"loki-prod/loki-canary\"}[1m]) > 0"
}
}

View File

@ -99,7 +99,7 @@
"AlertQuery": {
"properties": {
"datasourceUid": {
"description": "Grafana data source unique identifier; it should be '-100' for a Server Side Expression operation.",
"description": "Grafana data source unique identifier; it should be '__expr__' for a Server Side Expression operation.",
"type": "string"
},
"model": {
@ -2212,7 +2212,7 @@
"data": {
"example": [
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -3284,7 +3284,6 @@
"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"
@ -3320,7 +3319,7 @@
"$ref": "#/definitions/Userinfo"
}
},
"title": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"type": "object"
},
"Userinfo": {
@ -3497,6 +3496,7 @@
"type": "object"
},
"alertGroup": {
"description": "AlertGroup alert group",
"properties": {
"alerts": {
"description": "alerts",
@ -3624,6 +3624,7 @@
"type": "object"
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"properties": {
"annotations": {
"$ref": "#/definitions/labelSet"
@ -3685,7 +3686,6 @@
"type": "array"
},
"gettableSilence": {
"description": "GettableSilence gettable silence",
"properties": {
"comment": {
"description": "comment",
@ -3734,6 +3734,7 @@
"type": "object"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"items": {
"$ref": "#/definitions/gettableSilence"
},
@ -4854,4 +4855,4 @@
}
},
"swagger": "2.0"
}
}

View File

@ -118,7 +118,7 @@ type ProvisionedAlertRule struct {
// example: A
Condition string `json:"condition"`
// required: true
// example: [{"refId":"A","queryType":"","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"-100","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"}}]
// example: [{"refId":"A","queryType":"","relativeTimeRange":{"from":0,"to":0},"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"}}]
Data []models.AlertQuery `json:"data"`
// readonly: true
Updated time.Time `json:"updated,omitempty"`

View File

@ -99,7 +99,7 @@
"AlertQuery": {
"properties": {
"datasourceUid": {
"description": "Grafana data source unique identifier; it should be '-100' for a Server Side Expression operation.",
"description": "Grafana data source unique identifier; it should be '__expr__' for a Server Side Expression operation.",
"type": "string"
},
"model": {
@ -2212,7 +2212,7 @@
"data": {
"example": [
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -3284,7 +3284,6 @@
"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"
@ -3320,7 +3319,7 @@
"$ref": "#/definitions/Userinfo"
}
},
"title": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"type": "object"
},
"Userinfo": {
@ -3497,7 +3496,6 @@
"type": "object"
},
"alertGroup": {
"description": "AlertGroup alert group",
"properties": {
"alerts": {
"description": "alerts",
@ -3742,6 +3740,7 @@
"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",
@ -3885,7 +3884,6 @@
"type": "array"
},
"postableSilence": {
"description": "PostableSilence postable silence",
"properties": {
"comment": {
"description": "comment",
@ -3923,6 +3921,7 @@
"type": "object"
},
"receiver": {
"description": "Receiver receiver",
"properties": {
"active": {
"description": "active",
@ -6636,4 +6635,4 @@
}
},
"swagger": "2.0"
}
}

View File

@ -2711,7 +2711,7 @@
"title": "AlertQuery represents a single query associated with an alert definition.",
"properties": {
"datasourceUid": {
"description": "Grafana data source unique identifier; it should be '-100' for a Server Side Expression operation.",
"description": "Grafana data source unique identifier; it should be '__expr__' for a Server Side Expression operation.",
"type": "string"
},
"model": {
@ -4843,7 +4843,7 @@
},
"example": [
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -5899,9 +5899,8 @@
}
},
"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": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"properties": {
"ForceQuery": {
"type": "boolean"
@ -6112,7 +6111,6 @@
}
},
"alertGroup": {
"description": "AlertGroup alert group",
"type": "object",
"required": [
"alerts",
@ -6363,6 +6361,7 @@
"$ref": "#/definitions/gettableSilences"
},
"integration": {
"description": "Integration integration",
"type": "object",
"required": [
"name",
@ -6507,7 +6506,6 @@
}
},
"postableSilence": {
"description": "PostableSilence postable silence",
"type": "object",
"required": [
"comment",
@ -6546,6 +6544,7 @@
"$ref": "#/definitions/postableSilence"
},
"receiver": {
"description": "Receiver receiver",
"type": "object",
"required": [
"active",
@ -6676,4 +6675,4 @@
"type": "basic"
}
}
}
}

View File

@ -88,7 +88,7 @@ type AlertQuery struct {
// RelativeTimeRange is the relative Start and End of the query as sent by the frontend.
RelativeTimeRange RelativeTimeRange `json:"relativeTimeRange"`
// Grafana data source unique identifier; it should be '-100' for a Server Side Expression operation.
// Grafana data source unique identifier; it should be '__expr__' for a Server Side Expression operation.
DatasourceUID string `json:"datasourceUid"`
// JSON is the raw JSON query and includes the above properties as well as custom properties.

View File

@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -29,7 +30,7 @@ func TestAlertQuery(t *testing.T) {
"queryType": "metricQuery",
"extraParam": "some text"
}`),
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
},
expectedIsExpression: true,
expectedMaxPoints: int64(defaultMaxDataPoints),

View File

@ -300,7 +300,7 @@ func CreateClassicConditionExpression(refID string, inputRefID string, reducer s
return AlertQuery{
RefID: refID,
QueryType: expr.DatasourceType,
DatasourceUID: expr.OldDatasourceUID,
DatasourceUID: expr.DatasourceUID,
// the format corresponds to model `ClassicConditionJSON` in /pkg/expr/classic/classic.go
Model: json.RawMessage(fmt.Sprintf(`
{
@ -334,7 +334,7 @@ func CreateClassicConditionExpression(refID string, inputRefID string, reducer s
}
}
]
}`, refID, inputRefID, operation, threshold, reducer, expr.OldDatasourceUID, expr.DatasourceType)),
}`, refID, inputRefID, operation, threshold, reducer, expr.DatasourceUID, expr.DatasourceType)),
}
}

View File

@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/db"
@ -371,7 +372,7 @@ func createTestRule(title string, groupTitle string, orgID int64) models.AlertRu
{
RefID: "A",
Model: json.RawMessage("{}"),
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
RelativeTimeRange: models.RelativeTimeRange{
From: models.Duration(60),
To: models.Duration(0),

View File

@ -719,13 +719,13 @@ func withQueryForState(t *testing.T, evalResult eval.State) models.AlertRuleMuta
switch evalResult {
case eval.Normal:
expression = `{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"type":"math",
"expression":"2 + 1 < 1"
}`
case eval.Pending, eval.Alerting:
expression = `{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"type":"math",
"expression":"2 + 2 > 1"
}`
@ -734,7 +734,7 @@ func withQueryForState(t *testing.T, evalResult eval.State) models.AlertRuleMuta
}
case eval.Error:
expression = `{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"type":"math",
"expression":"$A"
}`
@ -746,7 +746,7 @@ func withQueryForState(t *testing.T, evalResult eval.State) models.AlertRuleMuta
rule.Condition = "A"
rule.Data = []models.AlertQuery{
{
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(expression),
RelativeTimeRange: models.RelativeTimeRange{
From: models.Duration(5 * time.Hour),

View File

@ -139,7 +139,7 @@ func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *s
Data: []models.AlertQuery{
{
Model: json.RawMessage(`{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"type":"math",
"expression":"2 + 2 > 1"
}`),

View File

@ -31,7 +31,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -49,7 +49,7 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200

View File

@ -30,7 +30,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -48,7 +48,7 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200

View File

@ -30,7 +30,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -48,7 +48,7 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200

View File

@ -30,7 +30,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -48,7 +48,7 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200

View File

@ -30,7 +30,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -48,7 +48,7 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200
@ -84,7 +84,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -102,9 +102,9 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200
refId: B
type: classic_conditions
type: classic_conditions

View File

@ -30,7 +30,7 @@ apiVersion: 1
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -48,7 +48,7 @@ apiVersion: 1
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200

View File

@ -41,7 +41,7 @@
"from": 0,
"to": 0
},
"datasourceUID": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -61,7 +61,7 @@
},
"reducer": {
"params": [
],
"type": "last"
},
@ -70,7 +70,7 @@
],
"datasource": {
"type": "__expr__",
"uid": "-100"
"uid": "__expr__"
},
"hide": false,
"intervalMs": 1000,
@ -84,4 +84,4 @@
]
}
]
}
}

View File

@ -30,7 +30,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -48,7 +48,7 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200

View File

@ -30,7 +30,7 @@ groups:
relativeTimeRange:
from: 0
to: 0
datasourceUID: "-100"
datasourceUid: "__expr__"
model:
conditions:
- evaluator:
@ -48,7 +48,7 @@ groups:
type: query
datasource:
type: __expr__
uid: "-100"
uid: "__expr__"
hide: false
intervalMs: 1000
maxDataPoints: 43200

View File

@ -467,7 +467,7 @@ func (c *fakePluginClient) QueryData(ctx context.Context, req *backend.QueryData
c.req = req
// If an expression query ends up getting directly queried, we want it to return an error in our test.
if req.PluginContext.PluginID == "__expr__" {
if req.PluginContext.PluginID == expr.DatasourceUID {
return nil, errors.New("cant query an expression datasource")
}

View File

@ -171,7 +171,7 @@ func migrateAlertRuleQueries(data []alertQuery) ([]alertQuery, error) {
result := make([]alertQuery, 0, len(data))
for _, d := range data {
// queries that are expression are not relevant, skip them.
if d.DatasourceUID == expr.OldDatasourceUID {
if d.DatasourceUID == expr.DatasourceType {
result = append(result, d)
continue
}

View File

@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/grafana/grafana/pkg/util"
)
@ -187,7 +188,7 @@ func transConditions(set dashAlertSettings, orgID int64, dsUIDMap dsUIDLookup) (
ccAlertQuery := alertQuery{
RefID: ccRefID,
Model: exprModelJSON,
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
}
newCond.Data = append(newCond.Data, ccAlertQuery)

View File

@ -10,6 +10,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
@ -253,7 +254,7 @@ func TestIntegrationAdminConfiguration_SendingToExternalAlertmanagers(t *testing
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -274,7 +275,7 @@ func TestIntegrationAdminConfiguration_SendingToExternalAlertmanagers(t *testing
_ = postRequest(t, ruleURL, buf.String(), http.StatusAccepted)
}
//Eventually, our Alertmanagers should receiver the alert.
// Eventually, our Alertmanagers should receiver the alert.
{
require.Eventually(t, func() bool {
return fakeAM1.AlertsCount() == 1 && fakeAM2.AlertsCount() == 1

View File

@ -12,6 +12,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -508,7 +509,7 @@ func TestIntegrationAlertAndGroupsQuery(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -649,7 +650,7 @@ func TestIntegrationRulerAccess(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -752,7 +753,7 @@ func TestIntegrationDeleteFolderWithRules(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "2 + 3 > 1",
"intervalMs": 1000,
@ -907,7 +908,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -937,7 +938,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -967,7 +968,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -998,7 +999,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -1058,7 +1059,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -1117,7 +1118,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -1137,7 +1138,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -1208,7 +1209,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003e 1",
"intervalMs":1000,
@ -1244,7 +1245,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003e 1",
"intervalMs":1000,
@ -1302,7 +1303,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 < 1"
@ -1375,7 +1376,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 < 1"
@ -1409,7 +1410,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -1483,7 +1484,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 < 1"
@ -1551,7 +1552,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003C 1",
"intervalMs":1000,
@ -1600,7 +1601,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 < 1"
@ -1660,7 +1661,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003C 1",
"intervalMs":1000,
@ -1745,7 +1746,7 @@ func TestIntegrationAlertRuleCRUD(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003C 1",
"intervalMs":1000,
@ -1957,7 +1958,7 @@ func TestIntegrationQuota(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -1992,7 +1993,7 @@ func TestIntegrationQuota(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 4 > 1"
@ -2051,7 +2052,7 @@ func TestIntegrationQuota(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 4 \u003E 1",
"intervalMs":1000,
@ -2122,7 +2123,7 @@ func TestIntegrationEval(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model": {
"type":"math",
"expression":"1 < 2"
@ -2186,7 +2187,7 @@ func TestIntegrationEval(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"type":"math",
"expression":"1 > 2"
@ -2250,7 +2251,7 @@ func TestIntegrationEval(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"type":"math",
"expression":"1 > 2"
@ -2351,7 +2352,7 @@ func TestIntegrationEval(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"type":"math",
"expression":"1 < 2"
@ -2408,7 +2409,7 @@ func TestIntegrationEval(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"type":"math",
"expression":"1 > 2"

View File

@ -220,14 +220,14 @@
},
{
"refId": "B",
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"queryType": "",
"model": {
"refId": "B",
"hide": false,
"type": "reduce",
"datasource": {
"uid": "-100",
"uid": "__expr__",
"type": "__expr__"
},
"conditions": [
@ -261,14 +261,14 @@
},
{
"refId": "C",
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"queryType": "",
"model": {
"refId": "C",
"hide": false,
"type": "threshold",
"datasource": {
"uid": "-100",
"uid": "__expr__",
"type": "__expr__"
},
"conditions": [
@ -303,4 +303,4 @@
}
]
}
}
}

View File

@ -17,6 +17,7 @@ import (
"time"
"github.com/grafana/alerting/alerting/notifier/channels"
"github.com/grafana/grafana/pkg/expr"
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
@ -979,7 +980,7 @@ func getRulesConfig(t *testing.T) string {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"

View File

@ -11,6 +11,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -104,7 +105,7 @@ func TestIntegrationPrometheusRules(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -124,7 +125,7 @@ func TestIntegrationPrometheusRules(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -180,7 +181,7 @@ func TestIntegrationPrometheusRules(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -237,7 +238,7 @@ func TestIntegrationPrometheusRules(t *testing.T) {
"rules": [{
"state": "inactive",
"name": "AlwaysFiring",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"-100\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"__expr__\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"duration": 10,
"annotations": {
"annotation1": "val1"
@ -252,7 +253,7 @@ func TestIntegrationPrometheusRules(t *testing.T) {
}, {
"state": "inactive",
"name": "AlwaysFiringButSilenced",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"-100\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"__expr__\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"health": "ok",
"type": "alerting",
"lastEvaluation": "0001-01-01T00:00:00Z",
@ -289,7 +290,7 @@ func TestIntegrationPrometheusRules(t *testing.T) {
"rules": [{
"state": "inactive",
"name": "AlwaysFiring",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"-100\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"__expr__\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"duration": 10,
"annotations": {
"annotation1": "val1"
@ -304,7 +305,7 @@ func TestIntegrationPrometheusRules(t *testing.T) {
}, {
"state": "inactive",
"name": "AlwaysFiringButSilenced",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"-100\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"__expr__\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"health": "ok",
"type": "alerting",
"lastEvaluation": "0001-01-01T00:00:00Z",
@ -371,7 +372,7 @@ func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -391,7 +392,7 @@ func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -434,7 +435,7 @@ func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) {
"rules": [{
"state": "inactive",
"name": "AlwaysFiring",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"-100\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"__expr__\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"duration": 10,
"annotations": {
"__dashboardUid__": "%s",
@ -447,7 +448,7 @@ func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) {
}, {
"state": "inactive",
"name": "AlwaysFiringButSilenced",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"-100\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"__expr__\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"health": "ok",
"type": "alerting",
"lastEvaluation": "0001-01-01T00:00:00Z",
@ -469,7 +470,7 @@ func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) {
"rules": [{
"state": "inactive",
"name": "AlwaysFiring",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"-100\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"query": "[{\"refId\":\"A\",\"queryType\":\"\",\"relativeTimeRange\":{\"from\":18000,\"to\":10800},\"datasourceUid\":\"__expr__\",\"model\":{\"expression\":\"2 + 3 \\u003e 1\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"type\":\"math\"}}]",
"duration": 10,
"annotations": {
"__dashboardUid__": "%s",

View File

@ -9,6 +9,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -101,7 +102,7 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003E 1",
"intervalMs":1000,
@ -151,7 +152,7 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003E 1",
"intervalMs":1000,
@ -224,7 +225,7 @@ func TestIntegrationAlertRulePermissions(t *testing.T) {
"from":18000,
"to":10800
},
"datasourceUid":"-100",
"datasourceUid":"__expr__",
"model":{
"expression":"2 + 3 \u003E 1",
"intervalMs":1000,
@ -297,7 +298,7 @@ func createRule(t *testing.T, client apiClient, folder string) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -437,7 +438,7 @@ func TestIntegrationRulerRulesFilterByDashboard(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -457,7 +458,7 @@ func TestIntegrationRulerRulesFilterByDashboard(t *testing.T) {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -499,7 +500,7 @@ func TestIntegrationRulerRulesFilterByDashboard(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "2 + 3 \u003e 1",
"intervalMs": 1000,
@ -532,7 +533,7 @@ func TestIntegrationRulerRulesFilterByDashboard(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "2 + 3 \u003e 1",
"intervalMs": 1000,
@ -577,7 +578,7 @@ func TestIntegrationRulerRulesFilterByDashboard(t *testing.T) {
"from": 18000,
"to": 10800
},
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"expression": "2 + 3 \u003e 1",
"intervalMs": 1000,
@ -889,7 +890,7 @@ func newTestingRuleConfig(t *testing.T) apimodels.PostableRuleGroupConfig {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"
@ -916,7 +917,7 @@ func newTestingRuleConfig(t *testing.T) apimodels.PostableRuleGroupConfig {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"

View File

@ -10,6 +10,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/expr"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -105,7 +106,7 @@ func alertRuleGen() func() apimodels.PostableExtendedRuleNode {
From: ngmodels.Duration(time.Duration(5) * time.Hour),
To: ngmodels.Duration(time.Duration(3) * time.Hour),
},
DatasourceUID: "-100",
DatasourceUID: expr.DatasourceUID,
Model: json.RawMessage(`{
"type": "math",
"expression": "2 + 3 > 1"

View File

@ -11176,7 +11176,7 @@
"title": "AlertQuery represents a single query associated with an alert definition.",
"properties": {
"datasourceUid": {
"description": "Grafana data source unique identifier; it should be '-100' for a Server Side Expression operation.",
"description": "Grafana data source unique identifier; it should be '__expr__' for a Server Side Expression operation.",
"type": "string"
},
"model": {
@ -15886,7 +15886,7 @@
},
"example": [
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -18056,9 +18056,8 @@
"type": "string"
},
"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": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"properties": {
"ForceQuery": {
"type": "boolean"
@ -18887,6 +18886,7 @@
}
},
"alertGroup": {
"description": "AlertGroup alert group",
"type": "object",
"required": [
"alerts",
@ -19014,6 +19014,7 @@
}
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"type": "object",
"required": [
"labels",
@ -19075,7 +19076,6 @@
}
},
"gettableSilence": {
"description": "GettableSilence gettable silence",
"type": "object",
"required": [
"comment",
@ -19124,6 +19124,7 @@
}
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"type": "array",
"items": {
"$ref": "#/definitions/gettableSilence"
@ -20786,4 +20787,4 @@
"name": "service_accounts"
}
]
}
}

View File

@ -39,7 +39,7 @@ exports[`PanelAlertTabContent Will render alerts belonging to panel and a button
},
},
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -64,7 +64,7 @@ exports[`PanelAlertTabContent Will render alerts belonging to panel and a button
],
"datasource": {
"type": "__expr__",
"uid": "-100",
"uid": "__expr__",
},
"expression": "A",
"hide": false,
@ -76,7 +76,7 @@ exports[`PanelAlertTabContent Will render alerts belonging to panel and a button
"refId": "B",
},
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -103,7 +103,7 @@ exports[`PanelAlertTabContent Will render alerts belonging to panel and a button
],
"datasource": {
"type": "__expr__",
"uid": "-100",
"uid": "__expr__",
},
"expression": "B",
"hide": false,

View File

@ -12,7 +12,7 @@ exports[`Query and expressions reducer should add a new expression 1`] = `
"refId": "A",
},
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -141,7 +141,7 @@ exports[`Query and expressions reducer should rewire expressions 1`] = `
"refId": "A",
},
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -187,7 +187,7 @@ exports[`Query and expressions reducer should set data queries 1`] = `
{
"queries": [
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -233,7 +233,7 @@ exports[`Query and expressions reducer should update an expression 1`] = `
{
"queries": [
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -287,7 +287,7 @@ exports[`Query and expressions reducer should update an expression refId and rew
"refId": "C",
},
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -341,7 +341,7 @@ exports[`Query and expressions reducer should update expression type 1`] = `
"refId": "A",
},
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{

View File

@ -151,7 +151,7 @@ describe('Query and expressions reducer', () => {
const expressionQuery: AlertQuery = {
refId: 'B',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
relativeTimeRange: { from: 900, to: 1000 },
model: {
queryType: 'query',
@ -166,7 +166,7 @@ describe('Query and expressions reducer', () => {
const expressionQuery2: AlertQuery = {
refId: 'C',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
relativeTimeRange: { from: 1, to: 3 },
model: {
queryType: 'query',
@ -205,7 +205,7 @@ describe('Query and expressions reducer', () => {
queryType: 'query',
},
{
datasourceUid: '-100',
datasourceUid: '__expr__',
relativeTimeRange: { from: 900, to: 1000 },
model: {
datasource: '__expr__',
@ -219,7 +219,7 @@ describe('Query and expressions reducer', () => {
refId: 'B',
},
{
datasourceUid: '-100',
datasourceUid: '__expr__',
relativeTimeRange: { from: 900, to: 1000 },
model: {
datasource: '__expr__',
@ -240,7 +240,7 @@ describe('Query and expressions reducer', () => {
const expressionQuery: AlertQuery = {
refId: 'B',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
queryType: 'query',
datasource: '__expr__',
@ -275,7 +275,7 @@ describe('Query and expressions reducer', () => {
queryType: 'query',
},
{
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
datasource: '__expr__',
expression: 'A',

View File

@ -25,7 +25,7 @@ describe('rule-editor', () => {
const classicCondition = {
refId: 'B',
datasourceUid: '-100',
datasourceUid: '__expr__',
queryType: '',
model: {
refId: 'B',
@ -55,7 +55,7 @@ describe('rule-editor', () => {
const mathExpression = {
refId: 'B',
datasourceUid: '-100',
datasourceUid: '__expr__',
queryType: '',
model: {
refId: 'B',
@ -68,7 +68,7 @@ describe('rule-editor', () => {
const reduceExpression = {
refId: 'B',
datasourceUid: '-100',
datasourceUid: '__expr__',
queryType: '',
model: {
refId: 'B',
@ -82,7 +82,7 @@ describe('rule-editor', () => {
const resampleExpression = {
refId: 'A',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
refId: 'A',
type: 'resample',
@ -101,14 +101,14 @@ describe('rule-editor', () => {
const thresholdExpression = {
refId: 'C',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
refId: 'C',
type: 'threshold',
expression: 'B',
datasource: {
type: '__expr__',
uid: '-100',
uid: '__expr__',
},
conditions: [
{
@ -253,7 +253,7 @@ describe('getThresholdsForQueries', () => {
const classicCondition = {
refId: 'B',
datasourceUid: '-100',
datasourceUid: '__expr__',
queryType: '',
model: {
refId: 'B',
@ -319,7 +319,7 @@ function createThresholdExample(thresholdType: string): AlertQuery[] {
const reduceExpression = {
refId: 'B',
datasourceUid: '-100',
datasourceUid: '__expr__',
queryType: '',
model: {
refId: 'B',
@ -333,7 +333,7 @@ function createThresholdExample(thresholdType: string): AlertQuery[] {
const thresholdExpression = {
refId: 'C',
datasourceUid: '-100',
datasourceUid: '__expr__',
queryType: '',
model: {
refId: 'C',

View File

@ -102,7 +102,7 @@ const grafanaAlert = {
refId: 'B',
queryType: '',
relativeTimeRange: { from: 0, to: 0 },
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
conditions: [
{

View File

@ -12,7 +12,7 @@ describe('timeRange', () => {
const expressionQuery: AlertQuery = {
refId: 'B',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
queryType: 'query',
datasource: '__expr__',
@ -40,7 +40,7 @@ describe('timeRange', () => {
const expressionQuery: AlertQuery = {
refId: 'C',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
queryType: 'query',
datasource: '__expr__',
@ -80,7 +80,7 @@ describe('timeRange', () => {
const expressionQuery: AlertQuery = {
refId: 'B',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
queryType: 'query',
datasource: '__expr__',
@ -105,7 +105,7 @@ describe('timeRange', () => {
const expressionQuery: AlertQuery = {
refId: 'C',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
queryType: 'query',
datasource: '__expr__',
@ -142,7 +142,7 @@ describe('timeRange', () => {
const expressionQuery: AlertQuery = {
refId: 'B',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
queryType: 'query',
datasource: '__expr__',
@ -175,7 +175,7 @@ describe('timeRange', () => {
const expressionQuery: AlertQuery = {
refId: 'B',
queryType: 'expression',
datasourceUid: '-100',
datasourceUid: '__expr__',
model: {
queryType: 'query',
datasource: '__expr__',

View File

@ -1,4 +1,4 @@
import { Observable, from, mergeMap } from 'rxjs';
import { from, mergeMap, Observable } from 'rxjs';
import {
DataQueryRequest,
@ -61,10 +61,9 @@ export class ExpressionDatasourceApi extends DataSourceWithBackend<ExpressionQue
}
/**
* MATCHES a constant in DataSourceWithBackend, this should be '__expr__'
* @deprecated
* MATCHES a constant in DataSourceWithBackend
*/
export const ExpressionDatasourceUID = '-100';
export const ExpressionDatasourceUID = '__expr__';
export const instanceSettings: DataSourceInstanceSettings = {
id: -100,

View File

@ -2361,7 +2361,7 @@
"AlertQuery": {
"properties": {
"datasourceUid": {
"description": "Grafana data source unique identifier; it should be '-100' for a Server Side Expression operation.",
"description": "Grafana data source unique identifier; it should be '__expr__' for a Server Side Expression operation.",
"type": "string"
},
"model": {
@ -7056,7 +7056,7 @@
"data": {
"example": [
{
"datasourceUid": "-100",
"datasourceUid": "__expr__",
"model": {
"conditions": [
{
@ -9241,7 +9241,6 @@
"type": "string"
},
"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"
@ -9277,7 +9276,7 @@
"$ref": "#/components/schemas/Userinfo"
}
},
"title": "A URL represents a parsed URL (technically, a URI reference).",
"title": "URL is a custom URL type that allows validation at configuration load time.",
"type": "object"
},
"UpdateAlertNotificationCommand": {
@ -10072,6 +10071,7 @@
"type": "object"
},
"alertGroup": {
"description": "AlertGroup alert group",
"properties": {
"alerts": {
"description": "alerts",
@ -10199,6 +10199,7 @@
"type": "object"
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"properties": {
"annotations": {
"$ref": "#/components/schemas/labelSet"
@ -10260,7 +10261,6 @@
"type": "array"
},
"gettableSilence": {
"description": "GettableSilence gettable silence",
"properties": {
"comment": {
"description": "comment",
@ -10309,6 +10309,7 @@
"type": "object"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"items": {
"$ref": "#/components/schemas/gettableSilence"
},