Alerting: Rename expression elements of Rules APIs (#110914)

This renames `data` to `expressions` for clarity in the rules apis.

Also makes certain fields that are redundant optional in the case of pure expressions, so that users don't have to specify them when they are not needed (e.g. not datasource queries).
This commit is contained in:
Moustafa Baiou
2025-09-12 22:15:55 +00:00
committed by GitHub
parent 3e0f57a407
commit cb7abbaa0f
19 changed files with 610 additions and 517 deletions
@@ -19,14 +19,24 @@ spec:
additionalProperties:
type: string
type: object
data:
execErrState:
default: Error
enum:
- Error
- Ok
- Alerting
- KeepLast
type: string
expressions:
additionalProperties:
properties:
datasourceUID:
description: The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
pattern: ^[a-zA-Z0-9_-]+$
type: string
model: {}
queryType:
description: The type of query if this is a query expression
type: string
relativeTimeRange:
properties:
@@ -41,21 +51,16 @@ spec:
- to
type: object
source:
description: |-
Used to mark the expression to be used as the final source for the rule evaluation
Only one expression in a rule can be marked as the source
For AlertRules, this is the expression that will be evaluated against the alerting condition
For RecordingRules, this is the expression that will be recorded
type: boolean
required:
- queryType
- datasourceUID
- model
type: object
type: object
execErrState:
default: Error
enum:
- Error
- Ok
- Alerting
- KeepLast
type: string
for:
allOf:
- pattern: ^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$
@@ -151,10 +156,10 @@ spec:
type: object
required:
- title
- data
- trigger
- noDataState
- execErrState
- expressions
type: object
x-kubernetes-preserve-unknown-fields: true
status:
@@ -207,14 +212,16 @@ spec:
schema:
spec:
properties:
data:
expressions:
additionalProperties:
properties:
datasourceUID:
description: The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
pattern: ^[a-zA-Z0-9_-]+$
type: string
model: {}
queryType:
description: The type of query if this is a query expression
type: string
relativeTimeRange:
properties:
@@ -229,10 +236,13 @@ spec:
- to
type: object
source:
description: |-
Used to mark the expression to be used as the final source for the rule evaluation
Only one expression in a rule can be marked as the source
For AlertRules, this is the expression that will be evaluated against the alerting condition
For RecordingRules, this is the expression that will be recorded
type: boolean
required:
- queryType
- datasourceUID
- model
type: object
type: object
@@ -263,9 +273,9 @@ spec:
type: object
required:
- title
- data
- trigger
- metric
- expressions
- targetDatasourceUID
type: object
x-kubernetes-preserve-unknown-fields: true
@@ -17,14 +17,24 @@ spec:
additionalProperties:
type: string
type: object
data:
execErrState:
default: Error
enum:
- Error
- Ok
- Alerting
- KeepLast
type: string
expressions:
additionalProperties:
properties:
datasourceUID:
description: The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
pattern: ^[a-zA-Z0-9_-]+$
type: string
model: {}
queryType:
description: The type of query if this is a query expression
type: string
relativeTimeRange:
properties:
@@ -39,21 +49,16 @@ spec:
- to
type: object
source:
description: |-
Used to mark the expression to be used as the final source for the rule evaluation
Only one expression in a rule can be marked as the source
For AlertRules, this is the expression that will be evaluated against the alerting condition
For RecordingRules, this is the expression that will be recorded
type: boolean
required:
- queryType
- datasourceUID
- model
type: object
type: object
execErrState:
default: Error
enum:
- Error
- Ok
- Alerting
- KeepLast
type: string
for:
allOf:
- pattern: ^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$
@@ -149,10 +154,10 @@ spec:
type: object
required:
- title
- data
- trigger
- noDataState
- execErrState
- expressions
type: object
x-kubernetes-preserve-unknown-fields: true
status:
@@ -13,14 +13,16 @@ spec:
properties:
spec:
properties:
data:
expressions:
additionalProperties:
properties:
datasourceUID:
description: The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
pattern: ^[a-zA-Z0-9_-]+$
type: string
model: {}
queryType:
description: The type of query if this is a query expression
type: string
relativeTimeRange:
properties:
@@ -35,10 +37,13 @@ spec:
- to
type: object
source:
description: |-
Used to mark the expression to be used as the final source for the rule evaluation
Only one expression in a rule can be marked as the source
For AlertRules, this is the expression that will be evaluated against the alerting condition
For RecordingRules, this is the expression that will be recorded
type: boolean
required:
- queryType
- datasourceUID
- model
type: object
type: object
@@ -69,9 +74,9 @@ spec:
type: object
required:
- title
- data
- trigger
- metric
- expressions
- targetDatasourceUID
type: object
x-kubernetes-preserve-unknown-fields: true
@@ -10,16 +10,16 @@ ExecErrState: *"Error" | "Ok" | "Alerting" | "KeepLast"
// FIXME: the For and KeepFiringFor types should be using the AlertRulePromDuration type, but there seems to be an issue with the generator
AlertRuleSpec: #RuleSpec & {
noDataState: NoDataState
execErrState: ExecErrState
"for"?: string & #PromDuration
keepFiringFor?: string & #PromDuration
missingSeriesEvalsToResolve?: int & >=0
notificationSettings?: #NotificationSettings
annotations?: {
[string]: TemplateString
}
panelRef?: #PanelRef
"for"?: string & #PromDuration
keepFiringFor?: string & #PromDuration
missingSeriesEvalsToResolve?: int & >=0
noDataState: NoDataState
execErrState: ExecErrState
notificationSettings?: #NotificationSettings
panelRef?: #PanelRef
}
#PanelRef: {
@@ -12,12 +12,12 @@ TemplateString: string
#RuleSpec: {
title: string
data: #QueryMap
paused?: bool
trigger: #IntervalTrigger
labels?: {
[string]: TemplateString
}
expressions: #ExpressionMap
...
}
@@ -34,15 +34,20 @@ TemplateString: string
}
// TODO: validate that only one can specify source=true
#QueryMap: {
[string]: #Query
#ExpressionMap: {
[string]: #Expression
} // & struct.MinFields(1) This doesn't work in Cue <v0.12.0 as per
// TODO: come up with a better name for this. We have expression type things and data source queries
#Query: {
queryType: string // TODO: consider making this optional, with the nil value meaning "__expr__" (i.e. expression query)
#Expression: {
// The type of query if this is a query expression
queryType?: string
relativeTimeRange?: #RelativeTimeRange
datasourceUID: #DatasourceUID
model: _
source?: bool
// The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
datasourceUID?: #DatasourceUID
model: _
// Used to mark the expression to be used as the final source for the rule evaluation
// Only one expression in a rule can be marked as the source
// For AlertRules, this is the expression that will be evaluated against the alerting condition
// For RecordingRules, this is the expression that will be recorded
source?: bool
}
@@ -2,25 +2,49 @@
package v0alpha1
// +k8s:openapi-gen=true
type AlertRuleIntervalTrigger struct {
Interval AlertRulePromDuration `json:"interval"`
}
// NewAlertRuleIntervalTrigger creates a new AlertRuleIntervalTrigger object.
func NewAlertRuleIntervalTrigger() *AlertRuleIntervalTrigger {
return &AlertRuleIntervalTrigger{}
}
// +k8s:openapi-gen=true
type AlertRulePromDuration string
// +k8s:openapi-gen=true
type AlertRuleTemplateString string
// TODO(@moustafab): validate regex for time interval ref
// +k8s:openapi-gen=true
type AlertRuleTimeIntervalRef string
// TODO: validate that only one can specify source=true
// & struct.MinFields(1) This doesn't work in Cue <v0.12.0 as per
// +k8s:openapi-gen=true
type AlertRuleQueryMap map[string]AlertRuleQuery
type AlertRuleExpressionMap map[string]AlertRuleExpression
// TODO: come up with a better name for this. We have expression type things and data source queries
// +k8s:openapi-gen=true
type AlertRuleQuery struct {
// TODO: consider making this optional, with the nil value meaning "__expr__" (i.e. expression query)
QueryType string `json:"queryType"`
type AlertRuleExpression struct {
// The type of query if this is a query expression
QueryType *string `json:"queryType,omitempty"`
RelativeTimeRange *AlertRuleRelativeTimeRange `json:"relativeTimeRange,omitempty"`
DatasourceUID AlertRuleDatasourceUID `json:"datasourceUID"`
Model interface{} `json:"model"`
Source *bool `json:"source,omitempty"`
// The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
DatasourceUID *AlertRuleDatasourceUID `json:"datasourceUID,omitempty"`
Model interface{} `json:"model"`
// Used to mark the expression to be used as the final source for the rule evaluation
// Only one expression in a rule can be marked as the source
// For AlertRules, this is the expression that will be evaluated against the alerting condition
// For RecordingRules, this is the expression that will be recorded
Source *bool `json:"source,omitempty"`
}
// NewAlertRuleQuery creates a new AlertRuleQuery object.
func NewAlertRuleQuery() *AlertRuleQuery {
return &AlertRuleQuery{}
// NewAlertRuleExpression creates a new AlertRuleExpression object.
func NewAlertRuleExpression() *AlertRuleExpression {
return &AlertRuleExpression{}
}
// +k8s:openapi-gen=true
@@ -40,40 +64,20 @@ type AlertRulePromDurationWMillis string
// +k8s:openapi-gen=true
type AlertRuleDatasourceUID string
// +k8s:openapi-gen=true
type AlertRuleIntervalTrigger struct {
Interval AlertRulePromDuration `json:"interval"`
}
// NewAlertRuleIntervalTrigger creates a new AlertRuleIntervalTrigger object.
func NewAlertRuleIntervalTrigger() *AlertRuleIntervalTrigger {
return &AlertRuleIntervalTrigger{}
}
// +k8s:openapi-gen=true
type AlertRulePromDuration string
// TODO(@moustafab): validate regex for time interval ref
// +k8s:openapi-gen=true
type AlertRuleTimeIntervalRef string
// +k8s:openapi-gen=true
type AlertRuleTemplateString string
// +k8s:openapi-gen=true
type AlertRuleSpec struct {
Title string `json:"title"`
Data AlertRuleQueryMap `json:"data"`
Paused *bool `json:"paused,omitempty"`
Trigger AlertRuleIntervalTrigger `json:"trigger"`
NoDataState string `json:"noDataState"`
ExecErrState string `json:"execErrState"`
Labels map[string]AlertRuleTemplateString `json:"labels,omitempty"`
Annotations map[string]AlertRuleTemplateString `json:"annotations,omitempty"`
For *string `json:"for,omitempty"`
KeepFiringFor *string `json:"keepFiringFor,omitempty"`
MissingSeriesEvalsToResolve *int64 `json:"missingSeriesEvalsToResolve,omitempty"`
NoDataState string `json:"noDataState"`
ExecErrState string `json:"execErrState"`
NotificationSettings *AlertRuleV0alpha1SpecNotificationSettings `json:"notificationSettings,omitempty"`
Annotations map[string]AlertRuleTemplateString `json:"annotations,omitempty"`
Labels map[string]AlertRuleTemplateString `json:"labels,omitempty"`
Expressions AlertRuleExpressionMap `json:"expressions"`
PanelRef *AlertRuleV0alpha1SpecPanelRef `json:"panelRef,omitempty"`
}
@@ -2,25 +2,45 @@
package v0alpha1
// +k8s:openapi-gen=true
type RecordingRuleIntervalTrigger struct {
Interval RecordingRulePromDuration `json:"interval"`
}
// NewRecordingRuleIntervalTrigger creates a new RecordingRuleIntervalTrigger object.
func NewRecordingRuleIntervalTrigger() *RecordingRuleIntervalTrigger {
return &RecordingRuleIntervalTrigger{}
}
// +k8s:openapi-gen=true
type RecordingRulePromDuration string
// +k8s:openapi-gen=true
type RecordingRuleTemplateString string
// TODO: validate that only one can specify source=true
// & struct.MinFields(1) This doesn't work in Cue <v0.12.0 as per
// +k8s:openapi-gen=true
type RecordingRuleQueryMap map[string]RecordingRuleQuery
type RecordingRuleExpressionMap map[string]RecordingRuleExpression
// TODO: come up with a better name for this. We have expression type things and data source queries
// +k8s:openapi-gen=true
type RecordingRuleQuery struct {
// TODO: consider making this optional, with the nil value meaning "__expr__" (i.e. expression query)
QueryType string `json:"queryType"`
type RecordingRuleExpression struct {
// The type of query if this is a query expression
QueryType *string `json:"queryType,omitempty"`
RelativeTimeRange *RecordingRuleRelativeTimeRange `json:"relativeTimeRange,omitempty"`
DatasourceUID RecordingRuleDatasourceUID `json:"datasourceUID"`
Model interface{} `json:"model"`
Source *bool `json:"source,omitempty"`
// The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
DatasourceUID *RecordingRuleDatasourceUID `json:"datasourceUID,omitempty"`
Model interface{} `json:"model"`
// Used to mark the expression to be used as the final source for the rule evaluation
// Only one expression in a rule can be marked as the source
// For AlertRules, this is the expression that will be evaluated against the alerting condition
// For RecordingRules, this is the expression that will be recorded
Source *bool `json:"source,omitempty"`
}
// NewRecordingRuleQuery creates a new RecordingRuleQuery object.
func NewRecordingRuleQuery() *RecordingRuleQuery {
return &RecordingRuleQuery{}
// NewRecordingRuleExpression creates a new RecordingRuleExpression object.
func NewRecordingRuleExpression() *RecordingRuleExpression {
return &RecordingRuleExpression{}
}
// +k8s:openapi-gen=true
@@ -40,30 +60,14 @@ type RecordingRulePromDurationWMillis string
// +k8s:openapi-gen=true
type RecordingRuleDatasourceUID string
// +k8s:openapi-gen=true
type RecordingRuleIntervalTrigger struct {
Interval RecordingRulePromDuration `json:"interval"`
}
// NewRecordingRuleIntervalTrigger creates a new RecordingRuleIntervalTrigger object.
func NewRecordingRuleIntervalTrigger() *RecordingRuleIntervalTrigger {
return &RecordingRuleIntervalTrigger{}
}
// +k8s:openapi-gen=true
type RecordingRulePromDuration string
// +k8s:openapi-gen=true
type RecordingRuleTemplateString string
// +k8s:openapi-gen=true
type RecordingRuleSpec struct {
Title string `json:"title"`
Data RecordingRuleQueryMap `json:"data"`
Paused *bool `json:"paused,omitempty"`
Trigger RecordingRuleIntervalTrigger `json:"trigger"`
Metric string `json:"metric"`
Labels map[string]RecordingRuleTemplateString `json:"labels,omitempty"`
Metric string `json:"metric"`
Expressions RecordingRuleExpressionMap `json:"expressions"`
TargetDatasourceUID string `json:"targetDatasourceUID"`
}
@@ -13,9 +13,9 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRule": schema_pkg_apis_alerting_v0alpha1_AlertRule(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleExpression": schema_pkg_apis_alerting_v0alpha1_AlertRuleExpression(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleIntervalTrigger": schema_pkg_apis_alerting_v0alpha1_AlertRuleIntervalTrigger(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleList": schema_pkg_apis_alerting_v0alpha1_AlertRuleList(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleQuery": schema_pkg_apis_alerting_v0alpha1_AlertRuleQuery(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleRelativeTimeRange": schema_pkg_apis_alerting_v0alpha1_AlertRuleRelativeTimeRange(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleSpec": schema_pkg_apis_alerting_v0alpha1_AlertRuleSpec(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleStatus": schema_pkg_apis_alerting_v0alpha1_AlertRuleStatus(ref),
@@ -23,9 +23,9 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleV0alpha1SpecPanelRef": schema_pkg_apis_alerting_v0alpha1_AlertRuleV0alpha1SpecPanelRef(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRulestatusOperatorState": schema_pkg_apis_alerting_v0alpha1_AlertRulestatusOperatorState(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRule": schema_pkg_apis_alerting_v0alpha1_RecordingRule(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleExpression": schema_pkg_apis_alerting_v0alpha1_RecordingRuleExpression(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleIntervalTrigger": schema_pkg_apis_alerting_v0alpha1_RecordingRuleIntervalTrigger(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleList": schema_pkg_apis_alerting_v0alpha1_RecordingRuleList(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleQuery": schema_pkg_apis_alerting_v0alpha1_RecordingRuleQuery(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleRelativeTimeRange": schema_pkg_apis_alerting_v0alpha1_RecordingRuleRelativeTimeRange(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleSpec": schema_pkg_apis_alerting_v0alpha1_RecordingRuleSpec(ref),
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleStatus": schema_pkg_apis_alerting_v0alpha1_RecordingRuleStatus(ref),
@@ -81,6 +81,53 @@ func schema_pkg_apis_alerting_v0alpha1_AlertRule(ref common.ReferenceCallback) c
}
}
func schema_pkg_apis_alerting_v0alpha1_AlertRuleExpression(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"queryType": {
SchemaProps: spec.SchemaProps{
Description: "The type of query if this is a query expression",
Type: []string{"string"},
Format: "",
},
},
"relativeTimeRange": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleRelativeTimeRange"),
},
},
"datasourceUID": {
SchemaProps: spec.SchemaProps{
Description: "The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource",
Type: []string{"string"},
Format: "",
},
},
"model": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Format: "",
},
},
"source": {
SchemaProps: spec.SchemaProps{
Description: "Used to mark the expression to be used as the final source for the rule evaluation Only one expression in a rule can be marked as the source For AlertRules, this is the expression that will be evaluated against the alerting condition For RecordingRules, this is the expression that will be recorded",
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"model"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleRelativeTimeRange"},
}
}
func schema_pkg_apis_alerting_v0alpha1_AlertRuleIntervalTrigger(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -149,52 +196,6 @@ func schema_pkg_apis_alerting_v0alpha1_AlertRuleList(ref common.ReferenceCallbac
}
}
func schema_pkg_apis_alerting_v0alpha1_AlertRuleQuery(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"queryType": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"relativeTimeRange": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleRelativeTimeRange"),
},
},
"datasourceUID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"model": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Format: "",
},
},
"source": {
SchemaProps: spec.SchemaProps{
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"queryType", "datasourceUID", "model"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleRelativeTimeRange"},
}
}
func schema_pkg_apis_alerting_v0alpha1_AlertRuleRelativeTimeRange(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -235,20 +236,6 @@ func schema_pkg_apis_alerting_v0alpha1_AlertRuleSpec(ref common.ReferenceCallbac
Format: "",
},
},
"data": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleQuery"),
},
},
},
},
},
"paused": {
SchemaProps: spec.SchemaProps{
Type: []string{"boolean"},
@@ -261,18 +248,34 @@ func schema_pkg_apis_alerting_v0alpha1_AlertRuleSpec(ref common.ReferenceCallbac
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleIntervalTrigger"),
},
},
"noDataState": {
"labels": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
"execErrState": {
"annotations": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
"for": {
@@ -293,36 +296,34 @@ func schema_pkg_apis_alerting_v0alpha1_AlertRuleSpec(ref common.ReferenceCallbac
Format: "int64",
},
},
"noDataState": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"execErrState": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"notificationSettings": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleV0alpha1SpecNotificationSettings"),
},
},
"annotations": {
"expressions": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
"labels": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleExpression"),
},
},
},
@@ -334,11 +335,11 @@ func schema_pkg_apis_alerting_v0alpha1_AlertRuleSpec(ref common.ReferenceCallbac
},
},
},
Required: []string{"title", "data", "trigger", "noDataState", "execErrState"},
Required: []string{"title", "trigger", "noDataState", "execErrState", "expressions"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleIntervalTrigger", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleQuery", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleV0alpha1SpecNotificationSettings", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleV0alpha1SpecPanelRef"},
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleExpression", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleIntervalTrigger", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleV0alpha1SpecNotificationSettings", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.AlertRuleV0alpha1SpecPanelRef"},
}
}
@@ -592,6 +593,53 @@ func schema_pkg_apis_alerting_v0alpha1_RecordingRule(ref common.ReferenceCallbac
}
}
func schema_pkg_apis_alerting_v0alpha1_RecordingRuleExpression(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"queryType": {
SchemaProps: spec.SchemaProps{
Description: "The type of query if this is a query expression",
Type: []string{"string"},
Format: "",
},
},
"relativeTimeRange": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleRelativeTimeRange"),
},
},
"datasourceUID": {
SchemaProps: spec.SchemaProps{
Description: "The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource",
Type: []string{"string"},
Format: "",
},
},
"model": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Format: "",
},
},
"source": {
SchemaProps: spec.SchemaProps{
Description: "Used to mark the expression to be used as the final source for the rule evaluation Only one expression in a rule can be marked as the source For AlertRules, this is the expression that will be evaluated against the alerting condition For RecordingRules, this is the expression that will be recorded",
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"model"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleRelativeTimeRange"},
}
}
func schema_pkg_apis_alerting_v0alpha1_RecordingRuleIntervalTrigger(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -660,52 +708,6 @@ func schema_pkg_apis_alerting_v0alpha1_RecordingRuleList(ref common.ReferenceCal
}
}
func schema_pkg_apis_alerting_v0alpha1_RecordingRuleQuery(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"queryType": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"relativeTimeRange": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleRelativeTimeRange"),
},
},
"datasourceUID": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"model": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Format: "",
},
},
"source": {
SchemaProps: spec.SchemaProps{
Type: []string{"boolean"},
Format: "",
},
},
},
Required: []string{"queryType", "datasourceUID", "model"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleRelativeTimeRange"},
}
}
func schema_pkg_apis_alerting_v0alpha1_RecordingRuleRelativeTimeRange(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -746,20 +748,6 @@ func schema_pkg_apis_alerting_v0alpha1_RecordingRuleSpec(ref common.ReferenceCal
Format: "",
},
},
"data": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleQuery"),
},
},
},
},
},
"paused": {
SchemaProps: spec.SchemaProps{
Type: []string{"boolean"},
@@ -772,13 +760,6 @@ func schema_pkg_apis_alerting_v0alpha1_RecordingRuleSpec(ref common.ReferenceCal
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleIntervalTrigger"),
},
},
"metric": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"labels": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
@@ -794,6 +775,27 @@ func schema_pkg_apis_alerting_v0alpha1_RecordingRuleSpec(ref common.ReferenceCal
},
},
},
"metric": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"expressions": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
AdditionalProperties: &spec.SchemaOrBool{
Allows: true,
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleExpression"),
},
},
},
},
},
"targetDatasourceUID": {
SchemaProps: spec.SchemaProps{
Default: "",
@@ -802,11 +804,11 @@ func schema_pkg_apis_alerting_v0alpha1_RecordingRuleSpec(ref common.ReferenceCal
},
},
},
Required: []string{"title", "data", "trigger", "metric", "targetDatasourceUID"},
Required: []string{"title", "trigger", "metric", "expressions", "targetDatasourceUID"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleIntervalTrigger", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleQuery"},
"github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleExpression", "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1.RecordingRuleIntervalTrigger"},
}
}
@@ -17,10 +17,10 @@ import (
)
var (
rawSchemaAlertRulev0alpha1 = []byte(`{"spec":{"properties":{"annotations":{"additionalProperties":{"type":"string"},"type":"object"},"data":{"additionalProperties":{"properties":{"datasourceUID":{"pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"model":{},"queryType":{"type":"string"},"relativeTimeRange":{"properties":{"from":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"},"to":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"}},"required":["from","to"],"type":"object"},"source":{"type":"boolean"}},"required":["queryType","datasourceUID","model"],"type":"object"},"type":"object"},"execErrState":{"default":"Error","enum":["Error","Ok","Alerting","KeepLast"],"type":"string"},"for":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"keepFiringFor":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"labels":{"additionalProperties":{"type":"string"},"type":"object"},"missingSeriesEvalsToResolve":{"minimum":0,"type":"integer"},"noDataState":{"default":"NoData","enum":["NoData","Ok","Alerting","KeepLast"],"type":"string"},"notificationSettings":{"properties":{"activeTimeIntervals":{"items":{"type":"string"},"type":"array"},"groupBy":{"items":{"type":"string"},"type":"array"},"groupInterval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"groupWait":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"muteTimeIntervals":{"items":{"type":"string"},"type":"array"},"receiver":{"type":"string"},"repeatInterval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"}},"required":["receiver"],"type":"object"},"panelRef":{"properties":{"dashboardUID":{"minLength":1,"pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"panelID":{"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"required":["dashboardUID","panelID"],"type":"object"},"paused":{"type":"boolean"},"title":{"type":"string"},"trigger":{"properties":{"interval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"}},"required":["interval"],"type":"object"}},"required":["title","data","trigger","noDataState","execErrState"],"type":"object","x-kubernetes-preserve-unknown-fields":true},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
rawSchemaAlertRulev0alpha1 = []byte(`{"spec":{"properties":{"annotations":{"additionalProperties":{"type":"string"},"type":"object"},"execErrState":{"default":"Error","enum":["Error","Ok","Alerting","KeepLast"],"type":"string"},"expressions":{"additionalProperties":{"properties":{"datasourceUID":{"description":"The UID of the datasource to run this expression against. If omitted, the expression will be run against the ` + "`" + `__expr__` + "`" + ` datasource","pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"model":{},"queryType":{"description":"The type of query if this is a query expression","type":"string"},"relativeTimeRange":{"properties":{"from":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"},"to":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"}},"required":["from","to"],"type":"object"},"source":{"description":"Used to mark the expression to be used as the final source for the rule evaluation\nOnly one expression in a rule can be marked as the source\nFor AlertRules, this is the expression that will be evaluated against the alerting condition\nFor RecordingRules, this is the expression that will be recorded","type":"boolean"}},"required":["model"],"type":"object"},"type":"object"},"for":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"keepFiringFor":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"labels":{"additionalProperties":{"type":"string"},"type":"object"},"missingSeriesEvalsToResolve":{"minimum":0,"type":"integer"},"noDataState":{"default":"NoData","enum":["NoData","Ok","Alerting","KeepLast"],"type":"string"},"notificationSettings":{"properties":{"activeTimeIntervals":{"items":{"type":"string"},"type":"array"},"groupBy":{"items":{"type":"string"},"type":"array"},"groupInterval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"groupWait":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"},"muteTimeIntervals":{"items":{"type":"string"},"type":"array"},"receiver":{"type":"string"},"repeatInterval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"}},"required":["receiver"],"type":"object"},"panelRef":{"properties":{"dashboardUID":{"minLength":1,"pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"panelID":{"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"required":["dashboardUID","panelID"],"type":"object"},"paused":{"type":"boolean"},"title":{"type":"string"},"trigger":{"properties":{"interval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"}},"required":["interval"],"type":"object"}},"required":["title","trigger","noDataState","execErrState","expressions"],"type":"object","x-kubernetes-preserve-unknown-fields":true},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaAlertRulev0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaAlertRulev0alpha1, &versionSchemaAlertRulev0alpha1)
rawSchemaRecordingRulev0alpha1 = []byte(`{"spec":{"properties":{"data":{"additionalProperties":{"properties":{"datasourceUID":{"pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"model":{},"queryType":{"type":"string"},"relativeTimeRange":{"properties":{"from":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"},"to":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"}},"required":["from","to"],"type":"object"},"source":{"type":"boolean"}},"required":["queryType","datasourceUID","model"],"type":"object"},"type":"object"},"labels":{"additionalProperties":{"type":"string"},"type":"object"},"metric":{"pattern":"^[a-zA-Z_:][a-zA-Z0-9_:]*$","type":"string"},"paused":{"type":"boolean"},"targetDatasourceUID":{"pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"title":{"type":"string"},"trigger":{"properties":{"interval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"}},"required":["interval"],"type":"object"}},"required":["title","data","trigger","metric","targetDatasourceUID"],"type":"object","x-kubernetes-preserve-unknown-fields":true},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
rawSchemaRecordingRulev0alpha1 = []byte(`{"spec":{"properties":{"expressions":{"additionalProperties":{"properties":{"datasourceUID":{"description":"The UID of the datasource to run this expression against. If omitted, the expression will be run against the ` + "`" + `__expr__` + "`" + ` datasource","pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"model":{},"queryType":{"description":"The type of query if this is a query expression","type":"string"},"relativeTimeRange":{"properties":{"from":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"},"to":{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$","type":"string"}},"required":["from","to"],"type":"object"},"source":{"description":"Used to mark the expression to be used as the final source for the rule evaluation\nOnly one expression in a rule can be marked as the source\nFor AlertRules, this is the expression that will be evaluated against the alerting condition\nFor RecordingRules, this is the expression that will be recorded","type":"boolean"}},"required":["model"],"type":"object"},"type":"object"},"labels":{"additionalProperties":{"type":"string"},"type":"object"},"metric":{"pattern":"^[a-zA-Z_:][a-zA-Z0-9_:]*$","type":"string"},"paused":{"type":"boolean"},"targetDatasourceUID":{"pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"title":{"type":"string"},"trigger":{"properties":{"interval":{"allOf":[{"pattern":"^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?|0)$"},{"not":{"pattern":"hmuµn"}}],"type":"string"}},"required":["interval"],"type":"object"}},"required":["title","trigger","metric","expressions","targetDatasourceUID"],"type":"object","x-kubernetes-preserve-unknown-fields":true},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`)
versionSchemaRecordingRulev0alpha1 app.VersionSchema
_ = json.Unmarshal(rawSchemaRecordingRulev0alpha1, &versionSchemaRecordingRulev0alpha1)
)
@@ -1,24 +1,47 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
export interface IntervalTrigger {
interval: PromDuration;
}
export const defaultIntervalTrigger = (): IntervalTrigger => ({
interval: defaultPromDuration(),
});
export type PromDuration = string;
export const defaultPromDuration = (): PromDuration => ("");
export type TemplateString = string;
export const defaultTemplateString = (): TemplateString => ("");
// TODO(@moustafab): validate regex for time interval ref
export type TimeIntervalRef = string;
export const defaultTimeIntervalRef = (): TimeIntervalRef => ("");
// TODO: validate that only one can specify source=true
// & struct.MinFields(1) This doesn't work in Cue <v0.12.0 as per
export type QueryMap = Record<string, Query>;
export type ExpressionMap = Record<string, Expression>;
export const defaultQueryMap = (): QueryMap => ({});
export const defaultExpressionMap = (): ExpressionMap => ({});
// TODO: come up with a better name for this. We have expression type things and data source queries
export interface Query {
// TODO: consider making this optional, with the nil value meaning "__expr__" (i.e. expression query)
queryType: string;
export interface Expression {
// The type of query if this is a query expression
queryType?: string;
relativeTimeRange?: RelativeTimeRange;
datasourceUID: DatasourceUID;
// The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
datasourceUID?: DatasourceUID;
model: any;
// Used to mark the expression to be used as the final source for the rule evaluation
// Only one expression in a rule can be marked as the source
// For AlertRules, this is the expression that will be evaluated against the alerting condition
// For RecordingRules, this is the expression that will be recorded
source?: boolean;
}
export const defaultQuery = (): Query => ({
queryType: "",
datasourceUID: defaultDatasourceUID(),
export const defaultExpression = (): Expression => ({
model: {},
});
@@ -40,37 +63,17 @@ export type DatasourceUID = string;
export const defaultDatasourceUID = (): DatasourceUID => ("");
export interface IntervalTrigger {
interval: PromDuration;
}
export const defaultIntervalTrigger = (): IntervalTrigger => ({
interval: defaultPromDuration(),
});
export type PromDuration = string;
export const defaultPromDuration = (): PromDuration => ("");
// TODO(@moustafab): validate regex for time interval ref
export type TimeIntervalRef = string;
export const defaultTimeIntervalRef = (): TimeIntervalRef => ("");
export type TemplateString = string;
export const defaultTemplateString = (): TemplateString => ("");
export interface Spec {
title: string;
data: QueryMap;
paused?: boolean;
trigger: IntervalTrigger;
noDataState: string;
execErrState: string;
labels?: Record<string, TemplateString>;
annotations?: Record<string, TemplateString>;
for?: string;
keepFiringFor?: string;
missingSeriesEvalsToResolve?: number;
noDataState: string;
execErrState: string;
notificationSettings?: {
receiver: string;
groupBy?: string[];
@@ -80,8 +83,7 @@ export interface Spec {
muteTimeIntervals?: TimeIntervalRef[];
activeTimeIntervals?: TimeIntervalRef[];
};
annotations?: Record<string, TemplateString>;
labels?: Record<string, TemplateString>;
expressions: ExpressionMap;
panelRef?: {
dashboardUID: string;
panelID: number;
@@ -90,9 +92,9 @@ export interface Spec {
export const defaultSpec = (): Spec => ({
title: "",
data: defaultQueryMap(),
trigger: defaultIntervalTrigger(),
noDataState: "NoData",
execErrState: "Error",
expressions: defaultExpressionMap(),
});
@@ -1,24 +1,42 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
export interface IntervalTrigger {
interval: PromDuration;
}
export const defaultIntervalTrigger = (): IntervalTrigger => ({
interval: defaultPromDuration(),
});
export type PromDuration = string;
export const defaultPromDuration = (): PromDuration => ("");
export type TemplateString = string;
export const defaultTemplateString = (): TemplateString => ("");
// TODO: validate that only one can specify source=true
// & struct.MinFields(1) This doesn't work in Cue <v0.12.0 as per
export type QueryMap = Record<string, Query>;
export type ExpressionMap = Record<string, Expression>;
export const defaultQueryMap = (): QueryMap => ({});
export const defaultExpressionMap = (): ExpressionMap => ({});
// TODO: come up with a better name for this. We have expression type things and data source queries
export interface Query {
// TODO: consider making this optional, with the nil value meaning "__expr__" (i.e. expression query)
queryType: string;
export interface Expression {
// The type of query if this is a query expression
queryType?: string;
relativeTimeRange?: RelativeTimeRange;
datasourceUID: DatasourceUID;
// The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource
datasourceUID?: DatasourceUID;
model: any;
// Used to mark the expression to be used as the final source for the rule evaluation
// Only one expression in a rule can be marked as the source
// For AlertRules, this is the expression that will be evaluated against the alerting condition
// For RecordingRules, this is the expression that will be recorded
source?: boolean;
}
export const defaultQuery = (): Query => ({
queryType: "",
datasourceUID: defaultDatasourceUID(),
export const defaultExpression = (): Expression => ({
model: {},
});
@@ -40,37 +58,21 @@ export type DatasourceUID = string;
export const defaultDatasourceUID = (): DatasourceUID => ("");
export interface IntervalTrigger {
interval: PromDuration;
}
export const defaultIntervalTrigger = (): IntervalTrigger => ({
interval: defaultPromDuration(),
});
export type PromDuration = string;
export const defaultPromDuration = (): PromDuration => ("");
export type TemplateString = string;
export const defaultTemplateString = (): TemplateString => ("");
export interface Spec {
title: string;
data: QueryMap;
paused?: boolean;
trigger: IntervalTrigger;
metric: string;
labels?: Record<string, TemplateString>;
metric: string;
expressions: ExpressionMap;
targetDatasourceUID: string;
}
export const defaultSpec = (): Spec => ({
title: "",
data: defaultQueryMap(),
trigger: defaultIntervalTrigger(),
metric: "",
expressions: defaultExpressionMap(),
targetDatasourceUID: "",
});
@@ -8,6 +8,7 @@ import (
"time"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/expr"
"github.com/grafana/grafana/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -43,8 +44,8 @@ func convertToK8sResource(
Labels: make(map[string]string),
},
Spec: model.AlertRuleSpec{
Title: rule.Title,
Data: make(map[string]model.AlertRuleQuery),
Title: rule.Title,
Expressions: make(model.AlertRuleExpressionMap),
Trigger: model.AlertRuleIntervalTrigger{
Interval: model.AlertRulePromDuration(interval.String()),
},
@@ -90,19 +91,7 @@ func convertToK8sResource(
}
for _, query := range rule.Data {
k8sQuery := model.AlertRuleQuery{
QueryType: query.QueryType,
Model: query.Model,
DatasourceUID: model.AlertRuleDatasourceUID(query.DatasourceUID),
Source: util.Pointer(rule.Condition == query.RefID),
}
if time.Duration(query.RelativeTimeRange.From) > 0 || time.Duration(query.RelativeTimeRange.To) > 0 {
k8sQuery.RelativeTimeRange = &model.AlertRuleRelativeTimeRange{
From: model.AlertRulePromDurationWMillis(query.RelativeTimeRange.From.String()),
To: model.AlertRulePromDurationWMillis(query.RelativeTimeRange.To.String()),
}
}
k8sRule.Spec.Data[query.RefID] = k8sQuery
k8sRule.Spec.Expressions[query.RefID] = convertToK8sExpression(query, rule)
}
for _, setting := range rule.NotificationSettings {
@@ -158,6 +147,29 @@ func convertToK8sResource(
return k8sRule, nil
}
func convertToK8sExpression(query ngmodels.AlertQuery, rule *ngmodels.AlertRule) model.AlertRuleExpression {
expression := model.AlertRuleExpression{
Model: query.Model,
}
if query.QueryType != "" {
expression.QueryType = util.Pointer(query.QueryType)
}
// DatasourceUID is optional and defaults to expr datasource
if !expr.IsDataSource(query.DatasourceUID) {
expression.DatasourceUID = util.Pointer(model.AlertRuleDatasourceUID(query.DatasourceUID))
}
if time.Duration(query.RelativeTimeRange.From) > 0 || time.Duration(query.RelativeTimeRange.To) > 0 {
expression.RelativeTimeRange = &model.AlertRuleRelativeTimeRange{
From: model.AlertRulePromDurationWMillis(query.RelativeTimeRange.From.String()),
To: model.AlertRulePromDurationWMillis(query.RelativeTimeRange.To.String()),
}
}
if rule.Condition == query.RefID {
expression.Source = util.Pointer(true)
}
return expression
}
func convertToK8sResources(
orgID int64,
rules []*ngmodels.AlertRule,
@@ -201,7 +213,7 @@ func convertToBaseDomainModel(orgID int64, k8sRule *model.AlertRule) (*ngmodels.
UID: k8sRule.Name,
Title: k8sRule.Spec.Title,
NamespaceUID: k8sRule.Namespace,
Data: make([]ngmodels.AlertQuery, 0, len(k8sRule.Spec.Data)),
Data: make([]ngmodels.AlertQuery, 0, len(k8sRule.Spec.Expressions)),
IsPaused: k8sRule.Spec.Paused != nil && *k8sRule.Spec.Paused,
Labels: make(map[string]string),
Annotations: make(map[string]string),
@@ -267,13 +279,13 @@ func convertToBaseDomainModel(orgID int64, k8sRule *model.AlertRule) (*ngmodels.
}
domainRule.IntervalSeconds = int64(time.Duration(interval).Seconds())
for refID, query := range k8sRule.Spec.Data {
domainQuery, err := convertToDomainQuery(query, refID)
for refID, expression := range k8sRule.Spec.Expressions {
domainQuery, err := convertToDomainQuery(expression, refID)
if err != nil {
return nil, err
}
domainRule.Data = append(domainRule.Data, domainQuery)
if query.Source != nil && *query.Source {
if expression.Source != nil && *expression.Source {
if domainRule.Condition != "" {
return nil, fmt.Errorf("multiple queries marked as source: %s and %s", domainRule.Condition, refID)
}
@@ -339,23 +351,29 @@ func convertNotificationSettings(sourceSettings *model.AlertRuleV0alpha1SpecNoti
return settings, nil
}
func convertToDomainQuery(query model.AlertRuleQuery, refID string) (ngmodels.AlertQuery, error) {
modelJson, err := json.Marshal(query.Model)
func convertToDomainQuery(expression model.AlertRuleExpression, refID string) (ngmodels.AlertQuery, error) {
modelJson, err := json.Marshal(expression.Model)
if err != nil {
return ngmodels.AlertQuery{}, fmt.Errorf("failed to marshal model: %w", err)
}
domainQuery := ngmodels.AlertQuery{
RefID: refID,
QueryType: query.QueryType,
DatasourceUID: string(query.DatasourceUID),
Model: modelJson,
RefID: refID,
Model: modelJson,
}
if query.RelativeTimeRange != nil {
from, err := prom_model.ParseDuration(string(query.RelativeTimeRange.From))
if expression.QueryType != nil {
domainQuery.QueryType = *expression.QueryType
}
if expression.DatasourceUID != nil {
domainQuery.DatasourceUID = string(*expression.DatasourceUID)
} else {
domainQuery.DatasourceUID = expr.DatasourceUID
}
if expression.RelativeTimeRange != nil {
from, err := prom_model.ParseDuration(string(expression.RelativeTimeRange.From))
if err != nil {
return ngmodels.AlertQuery{}, fmt.Errorf("failed to parse duration: %w", err)
}
to, err := prom_model.ParseDuration(string(query.RelativeTimeRange.To))
to, err := prom_model.ParseDuration(string(expression.RelativeTimeRange.To))
if err != nil {
return ngmodels.AlertQuery{}, fmt.Errorf("failed to parse duration: %w", err)
}
@@ -9,6 +9,7 @@ import (
model "github.com/grafana/grafana/apps/alerting/rules/pkg/apis/alerting/v0alpha1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/expr"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
@@ -42,8 +43,8 @@ func convertToK8sResource(
Labels: make(map[string]string),
},
Spec: model.RecordingRuleSpec{
Title: rule.Title,
Data: make(map[string]model.RecordingRuleQuery),
Title: rule.Title,
Expressions: make(model.RecordingRuleExpressionMap),
Trigger: model.RecordingRuleIntervalTrigger{
Interval: model.RecordingRulePromDuration(interval.String()),
},
@@ -67,21 +68,7 @@ func convertToK8sResource(
}
for _, query := range rule.Data {
k8sQuery := model.RecordingRuleQuery{
QueryType: query.QueryType,
Model: query.Model,
DatasourceUID: model.RecordingRuleDatasourceUID(query.DatasourceUID),
}
if time.Duration(query.RelativeTimeRange.From) > 0 || time.Duration(query.RelativeTimeRange.To) > 0 {
k8sQuery.RelativeTimeRange = &model.RecordingRuleRelativeTimeRange{
From: model.RecordingRulePromDurationWMillis(query.RelativeTimeRange.From.String()),
To: model.RecordingRulePromDurationWMillis(query.RelativeTimeRange.To.String()),
}
}
if rule.Record != nil && rule.Record.From == query.RefID {
k8sQuery.Source = util.Pointer(true)
}
k8sRule.Spec.Data[query.RefID] = k8sQuery
k8sRule.Spec.Expressions[query.RefID] = convertToK8sExpression(query, rule)
}
meta, err := utils.MetaAccessor(k8sRule)
@@ -108,6 +95,29 @@ func convertToK8sResource(
return k8sRule, nil
}
func convertToK8sExpression(query ngmodels.AlertQuery, rule *ngmodels.AlertRule) model.RecordingRuleExpression {
expression := model.RecordingRuleExpression{
Model: query.Model,
}
if query.QueryType != "" {
expression.QueryType = util.Pointer(query.QueryType)
}
// DatasourceUID is optional and defaults to expr datasource
if !expr.IsDataSource(query.DatasourceUID) {
expression.DatasourceUID = util.Pointer(model.RecordingRuleDatasourceUID(query.DatasourceUID))
}
if time.Duration(query.RelativeTimeRange.From) > 0 || time.Duration(query.RelativeTimeRange.To) > 0 {
expression.RelativeTimeRange = &model.RecordingRuleRelativeTimeRange{
From: model.RecordingRulePromDurationWMillis(query.RelativeTimeRange.From.String()),
To: model.RecordingRulePromDurationWMillis(query.RelativeTimeRange.To.String()),
}
}
if rule.Record != nil && rule.Record.From == query.RefID {
expression.Source = util.Pointer(true)
}
return expression
}
func convertToK8sResources(
orgID int64,
rules []*ngmodels.AlertRule,
@@ -150,7 +160,7 @@ func convertToBaseDomainModel(orgID int64, k8sRule *model.RecordingRule) (*ngmod
OrgID: orgID,
UID: k8sRule.Name,
Title: k8sRule.Spec.Title,
Data: make([]ngmodels.AlertQuery, 0, len(k8sRule.Spec.Data)),
Data: make([]ngmodels.AlertQuery, 0, len(k8sRule.Spec.Expressions)),
IsPaused: k8sRule.Spec.Paused != nil && *k8sRule.Spec.Paused,
Labels: make(map[string]string),
@@ -187,35 +197,13 @@ func convertToBaseDomainModel(orgID int64, k8sRule *model.RecordingRule) (*ngmod
for k, v := range k8sRule.Spec.Labels {
domainRule.Labels[k] = string(v)
}
for refID, query := range k8sRule.Spec.Data {
modelJson, err := json.Marshal(query.Model)
for refID, expression := range k8sRule.Spec.Expressions {
domainQuery, err := convertToDomainQuery(expression, refID)
if err != nil {
return nil, fmt.Errorf("failed to marshal model: %w", err)
return nil, err
}
domainQuery := ngmodels.AlertQuery{
RefID: refID,
QueryType: query.QueryType,
DatasourceUID: string(query.DatasourceUID),
Model: modelJson,
}
if query.RelativeTimeRange != nil {
from, err := prom_model.ParseDuration(string(query.RelativeTimeRange.From))
if err != nil {
return nil, fmt.Errorf("failed to parse duration: %w", err)
}
to, err := prom_model.ParseDuration(string(query.RelativeTimeRange.To))
if err != nil {
return nil, fmt.Errorf("failed to parse duration: %w", err)
}
domainQuery.RelativeTimeRange = ngmodels.RelativeTimeRange{
From: ngmodels.Duration(from),
To: ngmodels.Duration(to),
}
}
domainRule.Data = append(domainRule.Data, domainQuery)
if query.Source != nil && *query.Source {
if expression.Source != nil && *expression.Source {
if domainRule.Record.From != "" {
return nil, fmt.Errorf("multiple queries marked as source: %s and %s", domainRule.Record.From, refID)
}
@@ -227,3 +215,37 @@ func convertToBaseDomainModel(orgID int64, k8sRule *model.RecordingRule) (*ngmod
}
return domainRule, nil
}
func convertToDomainQuery(expression model.RecordingRuleExpression, refID string) (ngmodels.AlertQuery, error) {
modelJson, err := json.Marshal(expression.Model)
if err != nil {
return ngmodels.AlertQuery{}, fmt.Errorf("failed to marshal model: %w", err)
}
domainQuery := ngmodels.AlertQuery{
RefID: refID,
Model: modelJson,
}
if expression.QueryType != nil {
domainQuery.QueryType = *expression.QueryType
}
if expression.DatasourceUID != nil {
domainQuery.DatasourceUID = string(*expression.DatasourceUID)
} else {
domainQuery.DatasourceUID = expr.DatasourceUID
}
if expression.RelativeTimeRange != nil {
from, err := prom_model.ParseDuration(string(expression.RelativeTimeRange.From))
if err != nil {
return ngmodels.AlertQuery{}, fmt.Errorf("failed to parse duration: %w", err)
}
to, err := prom_model.ParseDuration(string(expression.RelativeTimeRange.To))
if err != nil {
return ngmodels.AlertQuery{}, fmt.Errorf("failed to parse duration: %w", err)
}
domainQuery.RelativeTimeRange = ngmodels.RelativeTimeRange{
From: ngmodels.Duration(from),
To: ngmodels.Duration(to),
}
}
return domainQuery, nil
}
@@ -54,10 +54,10 @@ func TestIntegrationResourceIdentifier(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer("query"),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -154,10 +154,10 @@ func TestIntegrationAccessControl(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -241,10 +241,10 @@ func TestIntegrationCRUD(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -295,10 +295,10 @@ func TestIntegrationCRUD(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -328,8 +328,8 @@ func TestIntegrationCRUD(t *testing.T) {
},
},
Spec: v0alpha1.AlertRuleSpec{
Title: "invalid-rule",
Data: map[string]v0alpha1.AlertRuleQuery{}, // Empty data should fail
Title: "invalid-rule",
Expressions: v0alpha1.AlertRuleExpressionMap{}, // Empty data should fail
Trigger: v0alpha1.AlertRuleIntervalTrigger{
Interval: "30",
},
@@ -356,10 +356,10 @@ func TestIntegrationCRUD(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -408,10 +408,10 @@ func TestIntegrationCRUD(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
From: v0alpha1.AlertRulePromDurationWMillis("5m"),
@@ -445,10 +445,10 @@ func TestIntegrationCRUD(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -501,10 +501,10 @@ func TestIntegrationPatch(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -57,10 +57,10 @@ func TestIntegrationAlertRuleCompatCreateViaK8s(t *testing.T) {
},
Spec: v0alpha1.AlertRuleSpec{
Title: rule.Title,
Data: map[string]v0alpha1.AlertRuleQuery{
Expressions: v0alpha1.AlertRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.AlertRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.AlertRuleRelativeTimeRange{
@@ -91,9 +91,9 @@ func TestIntegrationAlertRuleCompatCreateViaK8s(t *testing.T) {
err := json.Unmarshal(retrievedRule.Data[0].Model, &model)
require.NoError(t, err)
require.NotNil(t, model)
expectedModel, ok := created.Spec.Data["A"].Model.(map[string]interface{})
expectedModel, ok := created.Spec.Expressions["A"].Model.(map[string]interface{})
if !ok {
t.Fatalf("Expected model to be a map[string]interface{}, got %T", created.Spec.Data["A"].Model)
t.Fatalf("Expected model to be a map[string]interface{}, got %T", created.Spec.Expressions["A"].Model)
}
for k, v := range expectedModel {
require.EqualValues(t, v, model[k], "Model field %s should match", k)
@@ -230,13 +230,13 @@ func TestIntegrationAlertRuleCompatCreateViaProvisioning(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, retrievedRule)
require.Equal(t, r.Title, retrievedRule.Spec.Title)
require.NotNil(t, retrievedRule.Spec.Data[r.Data[0].RefID].Source)
require.True(t, *retrievedRule.Spec.Data[r.Data[0].RefID].Source)
require.NotNil(t, retrievedRule.Spec.Expressions[r.Data[0].RefID].Source)
require.True(t, *retrievedRule.Spec.Expressions[r.Data[0].RefID].Source)
require.Equal(t, r.FolderUID, retrievedRule.Annotations["grafana.app/folder"])
require.Equal(t, created.Title, retrievedRule.Labels[v0alpha1.GroupLabelKey])
require.Equal(t, fmt.Sprintf("%d", i), retrievedRule.Labels[v0alpha1.GroupIndexLabelKey])
require.Equal(t, ngmodels.ProvenanceAPI, ngmodels.Provenance(retrievedRule.GetProvenanceStatus()))
require.EqualValues(t, r.Data[0].DatasourceUID, retrievedRule.Spec.Data["A"].DatasourceUID)
require.EqualValues(t, r.Data[0].DatasourceUID, *retrievedRule.Spec.Expressions["A"].DatasourceUID)
expectedDuration, err := prom_model.ParseDuration(fmt.Sprintf("%ds", created.Interval))
require.NoError(t, err)
require.Equal(t, expectedDuration.String(), string(retrievedRule.Spec.Trigger.Interval))
@@ -244,9 +244,9 @@ func TestIntegrationAlertRuleCompatCreateViaProvisioning(t *testing.T) {
err = json.Unmarshal(r.Data[0].Model, &expectedModel)
require.NoError(t, err)
require.NotNil(t, expectedModel)
retrievedModel, ok := retrievedRule.Spec.Data["A"].Model.(map[string]interface{})
retrievedModel, ok := retrievedRule.Spec.Expressions["A"].Model.(map[string]interface{})
if !ok {
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Data["A"].Model)
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Expressions["A"].Model)
}
for k, v := range expectedModel {
require.EqualValues(t, v, retrievedModel[k], "Model field %s should match", k)
@@ -372,13 +372,13 @@ func TestIntegrationAlertRuleCompatCreateViaProvisioningChangeGroupInK8s(t *test
require.NoError(t, err)
require.NotNil(t, retrievedRule)
require.Equal(t, r.Title, retrievedRule.Spec.Title)
require.NotNil(t, retrievedRule.Spec.Data[r.Data[0].RefID].Source)
require.True(t, *retrievedRule.Spec.Data[r.Data[0].RefID].Source)
require.NotNil(t, retrievedRule.Spec.Expressions[r.Data[0].RefID].Source)
require.True(t, *retrievedRule.Spec.Expressions[r.Data[0].RefID].Source)
require.Equal(t, r.FolderUID, retrievedRule.Annotations["grafana.app/folder"])
require.Equal(t, created.Title, retrievedRule.Labels[v0alpha1.GroupLabelKey])
require.Equal(t, fmt.Sprintf("%d", i), retrievedRule.Labels[v0alpha1.GroupIndexLabelKey])
require.Equal(t, ngmodels.ProvenanceAPI, ngmodels.Provenance(retrievedRule.GetProvenanceStatus()))
require.EqualValues(t, r.Data[0].DatasourceUID, retrievedRule.Spec.Data["X"].DatasourceUID)
require.EqualValues(t, r.Data[0].DatasourceUID, *retrievedRule.Spec.Expressions["X"].DatasourceUID)
expectedDuration, err := prom_model.ParseDuration(fmt.Sprintf("%ds", created.Interval))
require.NoError(t, err)
require.Equal(t, expectedDuration.String(), string(retrievedRule.Spec.Trigger.Interval))
@@ -386,9 +386,9 @@ func TestIntegrationAlertRuleCompatCreateViaProvisioningChangeGroupInK8s(t *test
err = json.Unmarshal(r.Data[0].Model, &expectedModel)
require.NoError(t, err)
require.NotNil(t, expectedModel)
retrievedModel, ok := retrievedRule.Spec.Data["X"].Model.(map[string]interface{})
retrievedModel, ok := retrievedRule.Spec.Expressions["X"].Model.(map[string]interface{})
if !ok {
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Data["X"].Model)
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Expressions["X"].Model)
}
for k, v := range expectedModel {
require.EqualValues(t, v, retrievedModel[k], "Model field %s should match", k)
@@ -64,10 +64,10 @@ func TestIntegrationRecordingRuleCompatCreateViaK8s(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -98,9 +98,9 @@ func TestIntegrationRecordingRuleCompatCreateViaK8s(t *testing.T) {
err := json.Unmarshal(retrievedRule.Data[0].Model, &model)
require.NoError(t, err)
require.NotNil(t, model)
expectedModel, ok := created.Spec.Data["A"].Model.(map[string]interface{})
expectedModel, ok := created.Spec.Expressions["A"].Model.(map[string]interface{})
if !ok {
t.Fatalf("Expected model to be a map[string]interface{}, got %T", created.Spec.Data["A"].Model)
t.Fatalf("Expected model to be a map[string]interface{}, got %T", created.Spec.Expressions["A"].Model)
}
for k, v := range expectedModel {
require.EqualValues(t, v, model[k], "Model field %s should match", k)
@@ -247,7 +247,7 @@ func TestIntegrationRecordingRuleCompatCreateViaProvisioning(t *testing.T) {
require.Equal(t, created.Title, retrievedRule.Labels[v0alpha1.GroupLabelKey])
require.Equal(t, fmt.Sprintf("%d", i), retrievedRule.Labels[v0alpha1.GroupIndexLabelKey])
require.Equal(t, ngmodels.ProvenanceAPI, ngmodels.Provenance(retrievedRule.GetProvenanceStatus()))
require.EqualValues(t, r.Data[0].DatasourceUID, retrievedRule.Spec.Data["A"].DatasourceUID)
require.EqualValues(t, r.Data[0].DatasourceUID, *retrievedRule.Spec.Expressions["A"].DatasourceUID)
expectedDuration, err := prom_model.ParseDuration(fmt.Sprintf("%ds", created.Interval))
require.NoError(t, err)
require.Equal(t, expectedDuration.String(), string(retrievedRule.Spec.Trigger.Interval))
@@ -255,9 +255,9 @@ func TestIntegrationRecordingRuleCompatCreateViaProvisioning(t *testing.T) {
err = json.Unmarshal(r.Data[0].Model, &expectedModel)
require.NoError(t, err)
require.NotNil(t, expectedModel)
retrievedModel, ok := retrievedRule.Spec.Data["A"].Model.(map[string]interface{})
retrievedModel, ok := retrievedRule.Spec.Expressions["A"].Model.(map[string]interface{})
if !ok {
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Data["A"].Model)
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Expressions["A"].Model)
}
for k, v := range expectedModel {
require.EqualValues(t, v, retrievedModel[k], "Model field %s should match", k)
@@ -391,7 +391,7 @@ func TestIntegrationRecordingRuleCompatCreateViaProvisioningChangeGroupInK8s(t *
require.Equal(t, created.Title, retrievedRule.Labels[v0alpha1.GroupLabelKey])
require.Equal(t, fmt.Sprintf("%d", i), retrievedRule.Labels[v0alpha1.GroupIndexLabelKey])
require.Equal(t, ngmodels.ProvenanceAPI, ngmodels.Provenance(retrievedRule.GetProvenanceStatus()))
require.EqualValues(t, r.Data[0].DatasourceUID, retrievedRule.Spec.Data["X"].DatasourceUID)
require.EqualValues(t, r.Data[0].DatasourceUID, *retrievedRule.Spec.Expressions["X"].DatasourceUID)
expectedDuration, err := prom_model.ParseDuration(fmt.Sprintf("%ds", created.Interval))
require.NoError(t, err)
require.Equal(t, expectedDuration.String(), string(retrievedRule.Spec.Trigger.Interval))
@@ -399,9 +399,9 @@ func TestIntegrationRecordingRuleCompatCreateViaProvisioningChangeGroupInK8s(t *
err = json.Unmarshal(r.Data[0].Model, &expectedModel)
require.NoError(t, err)
require.NotNil(t, expectedModel)
retrievedModel, ok := retrievedRule.Spec.Data["X"].Model.(map[string]interface{})
retrievedModel, ok := retrievedRule.Spec.Expressions["X"].Model.(map[string]interface{})
if !ok {
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Data["X"].Model)
t.Fatalf("Expected model to be a map[string]interface{}, got %T", retrievedRule.Spec.Expressions["X"].Model)
}
for k, v := range expectedModel {
require.EqualValues(t, v, retrievedModel[k], "Model field %s should match", k)
@@ -55,10 +55,10 @@ func TestIntegrationResourceIdentifier(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -155,10 +155,10 @@ func TestIntegrationAccessControl(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -242,10 +242,10 @@ func TestIntegrationCRUD(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -294,10 +294,10 @@ func TestIntegrationCRUD(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -325,8 +325,8 @@ func TestIntegrationCRUD(t *testing.T) {
},
},
Spec: v0alpha1.RecordingRuleSpec{
Title: "invalid-recording-rule",
Data: map[string]v0alpha1.RecordingRuleQuery{}, // Empty data should fail
Title: "invalid-recording-rule",
Expressions: v0alpha1.RecordingRuleExpressionMap{}, // Empty data should fail
Trigger: v0alpha1.RecordingRuleIntervalTrigger{
Interval: "30s",
},
@@ -352,10 +352,10 @@ func TestIntegrationCRUD(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -404,10 +404,10 @@ func TestIntegrationCRUD(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
From: v0alpha1.RecordingRulePromDurationWMillis("5m"),
@@ -440,10 +440,10 @@ func TestIntegrationCRUD(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -496,10 +496,10 @@ func TestIntegrationPatch(t *testing.T) {
Spec: v0alpha1.RecordingRuleSpec{
Title: rule.Title,
Metric: rule.Record.Metric,
Data: map[string]v0alpha1.RecordingRuleQuery{
Expressions: v0alpha1.RecordingRuleExpressionMap{
"A": {
QueryType: "query",
DatasourceUID: v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID),
QueryType: util.Pointer(rule.Data[0].QueryType),
DatasourceUID: util.Pointer(v0alpha1.RecordingRuleDatasourceUID(rule.Data[0].DatasourceUID)),
Model: rule.Data[0].Model,
Source: util.Pointer(true),
RelativeTimeRange: &v0alpha1.RecordingRuleRelativeTimeRange{
@@ -2369,10 +2369,10 @@
"type": "object",
"required": [
"title",
"data",
"trigger",
"noDataState",
"execErrState"
"execErrState",
"expressions"
],
"properties": {
"annotations": {
@@ -2381,22 +2381,32 @@
"type": "string"
}
},
"data": {
"execErrState": {
"type": "string",
"default": "Error",
"enum": [
"Error",
"Ok",
"Alerting",
"KeepLast"
]
},
"expressions": {
"type": "object",
"additionalProperties": {
"type": "object",
"required": [
"queryType",
"datasourceUID",
"model"
],
"properties": {
"datasourceUID": {
"description": "The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource",
"type": "string",
"pattern": "^[a-zA-Z0-9_-]+$"
},
"model": {},
"queryType": {
"description": "The type of query if this is a query expression",
"type": "string"
},
"relativeTimeRange": {
@@ -2417,21 +2427,12 @@
}
},
"source": {
"description": "Used to mark the expression to be used as the final source for the rule evaluation\nOnly one expression in a rule can be marked as the source\nFor AlertRules, this is the expression that will be evaluated against the alerting condition\nFor RecordingRules, this is the expression that will be recorded",
"type": "boolean"
}
}
}
},
"execErrState": {
"type": "string",
"default": "Error",
"enum": [
"Error",
"Ok",
"Alerting",
"KeepLast"
]
},
"for": {
"type": "string",
"allOf": [
@@ -2730,28 +2731,28 @@
"type": "object",
"required": [
"title",
"data",
"trigger",
"metric",
"expressions",
"targetDatasourceUID"
],
"properties": {
"data": {
"expressions": {
"type": "object",
"additionalProperties": {
"type": "object",
"required": [
"queryType",
"datasourceUID",
"model"
],
"properties": {
"datasourceUID": {
"description": "The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource",
"type": "string",
"pattern": "^[a-zA-Z0-9_-]+$"
},
"model": {},
"queryType": {
"description": "The type of query if this is a query expression",
"type": "string"
},
"relativeTimeRange": {
@@ -2772,6 +2773,7 @@
}
},
"source": {
"description": "Used to mark the expression to be used as the final source for the rule evaluation\nOnly one expression in a rule can be marked as the source\nFor AlertRules, this is the expression that will be evaluated against the alerting condition\nFor RecordingRules, this is the expression that will be recorded",
"type": "boolean"
}
}
@@ -846,19 +846,25 @@ export type AlertRuleSpec = {
annotations?: {
[key: string]: string;
};
data: {
execErrState: 'Error' | 'Ok' | 'Alerting' | 'KeepLast';
expressions: {
[key: string]: {
datasourceUID: string;
/** The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource */
datasourceUID?: string;
model: any;
queryType: string;
/** The type of query if this is a query expression */
queryType?: string;
relativeTimeRange?: {
from: string;
to: string;
};
/** Used to mark the expression to be used as the final source for the rule evaluation
Only one expression in a rule can be marked as the source
For AlertRules, this is the expression that will be evaluated against the alerting condition
For RecordingRules, this is the expression that will be recorded */
source?: boolean;
};
};
execErrState: 'Error' | 'Ok' | 'Alerting' | 'KeepLast';
for?: any & any;
keepFiringFor?: any & any;
labels?: {
@@ -982,15 +988,21 @@ export type Status = {
};
export type Patch = object;
export type RecordingRuleSpec = {
data: {
expressions: {
[key: string]: {
datasourceUID: string;
/** The UID of the datasource to run this expression against. If omitted, the expression will be run against the `__expr__` datasource */
datasourceUID?: string;
model: any;
queryType: string;
/** The type of query if this is a query expression */
queryType?: string;
relativeTimeRange?: {
from: string;
to: string;
};
/** Used to mark the expression to be used as the final source for the rule evaluation
Only one expression in a rule can be marked as the source
For AlertRules, this is the expression that will be evaluated against the alerting condition
For RecordingRules, this is the expression that will be recorded */
source?: boolean;
};
};