-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
91 changed files
with
6,710 additions
and
268 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package v1beta1 | ||
|
||
import ( | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
// AlertingRuleSpec defines the desired state of AlertingRule | ||
type AlertingRuleSpec struct { | ||
// TenantID of tenant where the alerting rules are evaluated in. | ||
// | ||
// +required | ||
// +kubebuilder:validation:Required | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Tenant ID" | ||
TenantID string `json:"tenantID"` | ||
|
||
// List of groups for alerting rules. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Groups" | ||
Groups []*AlertingRuleGroup `json:"groups"` | ||
} | ||
|
||
// AlertingRuleGroup defines a group of Loki alerting rules. | ||
type AlertingRuleGroup struct { | ||
// Name of the alerting rule group. Must be unique within all alerting rules. | ||
// | ||
// +required | ||
// +kubebuilder:validation:Required | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Name" | ||
Name string `json:"name"` | ||
|
||
// Interval defines the time interval between evaluation of the given | ||
// alerting rule. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +kubebuilder:default:="1m" | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Evaluation Interval" | ||
Interval PrometheusDuration `json:"interval"` | ||
|
||
// Limit defines the number of alerts an alerting rule can produce. 0 is no limit. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:number",displayName="Limit of firing alerts" | ||
Limit int32 `json:"limit,omitempty"` | ||
|
||
// Rules defines a list of alerting rules | ||
// | ||
// +required | ||
// +kubebuilder:validation:Required | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Rules" | ||
Rules []*AlertingRuleGroupSpec `json:"rules"` | ||
} | ||
|
||
// AlertingRuleGroupSpec defines the spec for a Loki alerting rule. | ||
type AlertingRuleGroupSpec struct { | ||
// The name of the alert. Must be a valid label value. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Name" | ||
Alert string `json:"alert,omitempty"` | ||
|
||
// The LogQL expression to evaluate. Every evaluation cycle this is | ||
// evaluated at the current time, and all resultant time series become | ||
// pending/firing alerts. | ||
// | ||
// +required | ||
// +kubebuilder:validation:Required | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="LogQL Expression" | ||
Expr string `json:"expr"` | ||
|
||
// Alerts are considered firing once they have been returned for this long. | ||
// Alerts which have not yet fired for long enough are considered pending. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Firing Threshold" | ||
For PrometheusDuration `json:"for,omitempty"` | ||
|
||
// Annotations to add to each alert. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Annotations" | ||
Annotations map[string]string `json:"annotations,omitempty"` | ||
|
||
// Labels to add to each alert. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Labels" | ||
Labels map[string]string `json:"labels,omitempty"` | ||
} | ||
|
||
// AlertingRuleStatus defines the observed state of AlertingRule | ||
type AlertingRuleStatus struct { | ||
// Conditions of the AlertingRule generation health. | ||
// | ||
// +optional | ||
// +kubebuilder:validation:Optional | ||
// +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:io.kubernetes.conditions" | ||
Conditions []metav1.Condition `json:"conditions,omitempty"` | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
//+kubebuilder:subresource:status | ||
|
||
// AlertingRule is the Schema for the alertingrules API | ||
// | ||
// +operator-sdk:csv:customresourcedefinitions:displayName="AlertingRule",resources={{LokiStack,v1beta1}} | ||
type AlertingRule struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
Spec AlertingRuleSpec `json:"spec,omitempty"` | ||
Status AlertingRuleStatus `json:"status,omitempty"` | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
|
||
// AlertingRuleList contains a list of AlertingRule | ||
type AlertingRuleList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []AlertingRule `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&AlertingRule{}, &AlertingRuleList{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package v1beta1 | ||
|
||
import ( | ||
"github.com/grafana/loki/pkg/logql/syntax" | ||
|
||
"github.com/prometheus/common/model" | ||
|
||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
"k8s.io/apimachinery/pkg/util/validation/field" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
"sigs.k8s.io/controller-runtime/pkg/webhook" | ||
) | ||
|
||
// SetupWebhookWithManager registers the AlertingRuleWebhook to the controller-runtime manager | ||
// or returns an error. | ||
func (r *AlertingRule) SetupWebhookWithManager(mgr ctrl.Manager) error { | ||
return ctrl.NewWebhookManagedBy(mgr). | ||
For(r). | ||
Complete() | ||
} | ||
|
||
//+kubebuilder:webhook:path=/validate-loki-grafana-com-v1beta1-alertingrule,mutating=false,failurePolicy=fail,sideEffects=None,groups=loki.grafana.com,resources=alertingrules,verbs=create;update,versions=v1beta1,name=valertingrule.kb.io,admissionReviewVersions=v1 | ||
|
||
var _ webhook.Validator = &AlertingRule{} | ||
|
||
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type | ||
func (r *AlertingRule) ValidateCreate() error { | ||
return r.validate() | ||
} | ||
|
||
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type | ||
func (r *AlertingRule) ValidateUpdate(_ runtime.Object) error { | ||
return r.validate() | ||
} | ||
|
||
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type | ||
func (r *AlertingRule) ValidateDelete() error { | ||
// Do nothing | ||
return nil | ||
} | ||
|
||
func (r *AlertingRule) validate() error { | ||
var allErrs field.ErrorList | ||
|
||
found := make(map[string]bool) | ||
|
||
for i, g := range r.Spec.Groups { | ||
// Check for group name uniqueness | ||
if found[g.Name] { | ||
allErrs = append(allErrs, field.Invalid( | ||
field.NewPath("Spec").Child("Groups").Index(i).Child("Name"), | ||
g.Name, | ||
ErrGroupNamesNotUnique.Error(), | ||
)) | ||
} | ||
|
||
found[g.Name] = true | ||
|
||
// Check if rule evaluation period is a valid PromQL duration | ||
_, err := model.ParseDuration(string(g.Interval)) | ||
if err != nil { | ||
allErrs = append(allErrs, field.Invalid( | ||
field.NewPath("Spec").Child("Groups").Index(i).Child("Interval"), | ||
g.Interval, | ||
ErrParseEvaluationInterval.Error(), | ||
)) | ||
} | ||
|
||
for j, r := range g.Rules { | ||
// Check if alert for period is a valid PromQL duration | ||
if r.Alert != "" { | ||
_, err := model.ParseDuration(string(r.For)) | ||
if err != nil { | ||
allErrs = append(allErrs, field.Invalid( | ||
field.NewPath("Spec").Child("Groups").Index(i).Child("Rules").Index(j).Child("For"), | ||
r.For, | ||
ErrParseAlertForPeriod.Error(), | ||
)) | ||
} | ||
} | ||
|
||
// Check if the LogQL parser can parse the rule expression | ||
_, err := syntax.ParseExpr(r.Expr) | ||
if err != nil { | ||
allErrs = append(allErrs, field.Invalid( | ||
field.NewPath("Spec").Child("Groups").Index(i).Child("Rules").Index(j).Child("Expr"), | ||
r.Expr, | ||
ErrParseLogQLExpression.Error(), | ||
)) | ||
} | ||
} | ||
} | ||
|
||
if len(allErrs) == 0 { | ||
return nil | ||
} | ||
|
||
return apierrors.NewInvalid( | ||
schema.GroupKind{Group: "loki.grafana.com", Kind: "AlertingRule"}, | ||
r.Name, | ||
allErrs, | ||
) | ||
} |
Oops, something went wrong.