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:
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user