add alerting v2beta1 apis (#5115)
* generate alerting resource client Signed-off-by: junot <junotxiang@kubesphere.io> * add alerting v2beta1 apis Signed-off-by: junot <junotxiang@kubesphere.io> * tweak some varibles and descs Signed-off-by: junot <junotxiang@kubesphere.io>
This commit is contained in:
620
pkg/models/alerting/rulegroup.go
Normal file
620
pkg/models/alerting/rulegroup.go
Normal file
@@ -0,0 +1,620 @@
|
||||
// Copyright 2022 The KubeSphere Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package alerting
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
promlabels "github.com/prometheus/prometheus/pkg/labels"
|
||||
promrules "github.com/prometheus/prometheus/rules"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
kapialertingv2beta1 "kubesphere.io/kubesphere/pkg/api/alerting/v2beta1"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
controller "kubesphere.io/kubesphere/pkg/controller/alerting"
|
||||
resources "kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||
)
|
||||
|
||||
type RuleGroupOperator interface {
|
||||
ListRuleGroups(ctx context.Context, namespace string, queryParam *query.Query) (*api.ListResult, error)
|
||||
GetRuleGroup(ctx context.Context, namespace, name string) (*kapialertingv2beta1.RuleGroup, error)
|
||||
ListAlerts(ctx context.Context, namespace string, queryParam *query.Query) (*api.ListResult, error)
|
||||
|
||||
ListGlobalRuleGroups(ctx context.Context, queryParam *query.Query) (*api.ListResult, error)
|
||||
GetGlobalRuleGroup(ctx context.Context, name string) (*kapialertingv2beta1.GlobalRuleGroup, error)
|
||||
ListGlobalAlerts(ctx context.Context, queryParam *query.Query) (*api.ListResult, error)
|
||||
|
||||
ListClusterRuleGroups(ctx context.Context, queryParam *query.Query) (*api.ListResult, error)
|
||||
GetClusterRuleGroup(ctx context.Context, name string) (*kapialertingv2beta1.ClusterRuleGroup, error)
|
||||
ListClusterAlerts(ctx context.Context, queryParam *query.Query) (*api.ListResult, error)
|
||||
}
|
||||
|
||||
func NewRuleGroupOperator(ksclient kubesphere.Interface, ruleClient alerting.RuleClient) RuleGroupOperator {
|
||||
return &ruleGroupOperator{
|
||||
ksclient: ksclient,
|
||||
ruleClient: ruleClient,
|
||||
}
|
||||
}
|
||||
|
||||
type ruleGroupOperator struct {
|
||||
ruleClient alerting.RuleClient
|
||||
ksclient kubesphere.Interface
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) listRuleGroups(ctx context.Context, namespace string, selector labels.Selector) ([]runtime.Object, error) {
|
||||
resourceRuleGroups, err := o.ksclient.AlertingV2beta1().RuleGroups(namespace).List(ctx,
|
||||
metav1.ListOptions{
|
||||
LabelSelector: selector.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get rules matching '{rule_level="namespace",namespace="<namespace>"}' from thanos ruler
|
||||
matchers := []*promlabels.Matcher{{
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyRuleLevel,
|
||||
Value: string(controller.RuleLevelNamesapce),
|
||||
}, {
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyNamespace,
|
||||
Value: namespace,
|
||||
}}
|
||||
statusRuleGroups, err := o.ruleClient.ThanosRules(ctx, matchers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var statusRuleGroupMap = make(map[string]*alerting.RuleGroup)
|
||||
for i := range statusRuleGroups {
|
||||
g := statusRuleGroups[i]
|
||||
// the matchers only filter rules and all groups still return,
|
||||
// and some of them may be with empty rules, so here check them and skip some.
|
||||
if len(g.Rules) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := statusRuleGroupMap[g.Name]; !ok {
|
||||
statusRuleGroupMap[g.Name] = g
|
||||
}
|
||||
}
|
||||
|
||||
// copy status info of statusRuleGroups to matched rulegroups
|
||||
var groups = make([]runtime.Object, len(resourceRuleGroups.Items))
|
||||
for i := range resourceRuleGroups.Items {
|
||||
g := &kapialertingv2beta1.RuleGroup{
|
||||
RuleGroup: resourceRuleGroups.Items[i],
|
||||
Status: kapialertingv2beta1.RuleGroupStatus{
|
||||
State: promrules.StateInactive.String(),
|
||||
},
|
||||
}
|
||||
statusg, ok := statusRuleGroupMap[g.Name]
|
||||
if ok && len(statusg.Rules) == len(g.Spec.Rules) { // assure that they are the same rulegroups
|
||||
copyRuleGroupStatus(statusg, &g.Status)
|
||||
}
|
||||
groups[i] = g
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) ListRuleGroups(ctx context.Context, namespace string,
|
||||
queryParam *query.Query) (*api.ListResult, error) {
|
||||
|
||||
groups, err := o.listRuleGroups(ctx, namespace, queryParam.Selector())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resources.DefaultList(groups, queryParam, func(left, right runtime.Object, field query.Field) bool {
|
||||
hit, great := o.compareRuleGroupStatus(
|
||||
&(left.(*kapialertingv2beta1.RuleGroup).Status), &(right.(*kapialertingv2beta1.RuleGroup).Status), field)
|
||||
if hit {
|
||||
return great
|
||||
}
|
||||
return resources.DefaultObjectMetaCompare(
|
||||
left.(*kapialertingv2beta1.RuleGroup).ObjectMeta, right.(*kapialertingv2beta1.RuleGroup).ObjectMeta, field)
|
||||
}, func(obj runtime.Object, filter query.Filter) bool {
|
||||
hit, selected := o.filterRuleGroupStatus(&obj.(*kapialertingv2beta1.RuleGroup).Status, filter)
|
||||
if hit {
|
||||
return selected
|
||||
}
|
||||
return resources.DefaultObjectMetaFilter(obj.(*kapialertingv2beta1.RuleGroup).ObjectMeta, filter)
|
||||
}), nil
|
||||
}
|
||||
|
||||
// compareRuleGroupStatus compare rulegroup status.
|
||||
// if field in status, return hit(true) and great(true if left great than right, else false).
|
||||
// if filed not in status, return hit(false) and great(false, should be unuseful).
|
||||
func (d *ruleGroupOperator) compareRuleGroupStatus(left, right *kapialertingv2beta1.RuleGroupStatus, field query.Field) (hit, great bool) {
|
||||
|
||||
switch field {
|
||||
case kapialertingv2beta1.FieldRuleGroupEvaluationTime:
|
||||
hit = true
|
||||
if left.EvaluationTime == nil {
|
||||
great = false
|
||||
} else if right.EvaluationTime == nil {
|
||||
great = true
|
||||
} else {
|
||||
great = *left.EvaluationTime > *right.EvaluationTime
|
||||
}
|
||||
case kapialertingv2beta1.FieldRuleGroupLastEvaluation:
|
||||
hit = true
|
||||
if left.LastEvaluation == nil {
|
||||
great = false
|
||||
} else if right.LastEvaluation == nil {
|
||||
great = true
|
||||
} else {
|
||||
great = left.LastEvaluation.After(*right.LastEvaluation)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// filterRuleGroupStatus filters by rulegroup status.
|
||||
// if field in status, return hit(true) and selected(true if match the filter, else false).
|
||||
// if filed not in status, return hit(false) and selected(false, should be unuseful).
|
||||
func (d *ruleGroupOperator) filterRuleGroupStatus(status *kapialertingv2beta1.RuleGroupStatus, filter query.Filter) (hit, selected bool) {
|
||||
|
||||
switch filter.Field {
|
||||
case kapialertingv2beta1.FieldState:
|
||||
hit = true
|
||||
selected = status.State == string(filter.Value)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) ListAlerts(ctx context.Context, namespace string,
|
||||
queryParam *query.Query) (*api.ListResult, error) {
|
||||
|
||||
groups, err := o.listRuleGroups(ctx, namespace, labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// encapsulated as runtime.Object for easy comparison and filtering.
|
||||
var alerts []runtime.Object
|
||||
for i := range groups {
|
||||
g := groups[i].(*kapialertingv2beta1.RuleGroup)
|
||||
for j := range g.Status.RulesStatus {
|
||||
ruleStatus := g.Status.RulesStatus[j]
|
||||
for k := range ruleStatus.Alerts {
|
||||
alerts = append(alerts, &wrapAlert{Alert: *ruleStatus.Alerts[k]})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filterAlert := o.createFilterAlertFunc(queryParam)
|
||||
listResult := resources.DefaultList(alerts, queryParam, func(left, right runtime.Object, field query.Field) bool {
|
||||
return o.compareAlert(&left.(*wrapAlert).Alert, &right.(*wrapAlert).Alert, field)
|
||||
}, func(obj runtime.Object, filter query.Filter) bool {
|
||||
return filterAlert(&obj.(*wrapAlert).Alert, filter)
|
||||
})
|
||||
for i := range listResult.Items {
|
||||
listResult.Items[i] = &listResult.Items[i].(*wrapAlert).Alert
|
||||
}
|
||||
return listResult, nil
|
||||
}
|
||||
|
||||
func (d *ruleGroupOperator) compareAlert(left, right *kapialertingv2beta1.Alert, field query.Field) bool {
|
||||
switch field {
|
||||
case kapialertingv2beta1.FieldAlertActiveAt:
|
||||
if left.ActiveAt == nil {
|
||||
return false
|
||||
}
|
||||
if right.ActiveAt == nil {
|
||||
return true
|
||||
}
|
||||
return left.ActiveAt.After(*right.ActiveAt)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *ruleGroupOperator) createFilterAlertFunc(queryParam *query.Query) func(alert *kapialertingv2beta1.Alert, filter query.Filter) bool {
|
||||
var labelFilters kapialertingv2beta1.LabelFilters
|
||||
if len(queryParam.Filters) > 0 {
|
||||
if filters, ok := queryParam.Filters[kapialertingv2beta1.FieldAlertLabelFilters]; ok {
|
||||
labelFilters = kapialertingv2beta1.ParseLabelFilters(string(filters))
|
||||
}
|
||||
}
|
||||
return func(alert *kapialertingv2beta1.Alert, filter query.Filter) bool {
|
||||
switch filter.Field {
|
||||
case kapialertingv2beta1.FieldAlertLabelFilters:
|
||||
if labelFilters == nil {
|
||||
return true
|
||||
}
|
||||
return labelFilters.Matches(alert.Labels)
|
||||
case kapialertingv2beta1.FieldState:
|
||||
return alert.State == string(filter.Value)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) GetRuleGroup(ctx context.Context, namespace, name string) (*kapialertingv2beta1.RuleGroup, error) {
|
||||
resourceRuleGroup, err := o.ksclient.AlertingV2beta1().RuleGroups(namespace).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &kapialertingv2beta1.RuleGroup{
|
||||
RuleGroup: *resourceRuleGroup,
|
||||
Status: kapialertingv2beta1.RuleGroupStatus{
|
||||
State: promrules.StateInactive.String(),
|
||||
},
|
||||
}
|
||||
|
||||
matchers := []*promlabels.Matcher{{
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyRuleLevel,
|
||||
Value: string(controller.RuleLevelNamesapce),
|
||||
}, {
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyNamespace,
|
||||
Value: namespace,
|
||||
}}
|
||||
statusRuleGroups, err := o.ruleClient.ThanosRules(ctx, matchers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, g := range statusRuleGroups {
|
||||
if g.Name == resourceRuleGroup.Name && len(g.Rules) == len(resourceRuleGroup.Spec.Rules) {
|
||||
copyRuleGroupStatus(g, &ret.Status)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) listClusterRuleGroups(ctx context.Context, selector labels.Selector) ([]runtime.Object, error) {
|
||||
resourceRuleGroups, err := o.ksclient.AlertingV2beta1().ClusterRuleGroups().List(ctx, metav1.ListOptions{
|
||||
LabelSelector: selector.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get rules matching '{rule_level="cluster"}' from thanos ruler
|
||||
matchers := []*promlabels.Matcher{{
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyRuleLevel,
|
||||
Value: string(controller.RuleLevelCluster),
|
||||
}}
|
||||
statusRuleGroups, err := o.ruleClient.ThanosRules(ctx, matchers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var statusRuleGroupMap = make(map[string]*alerting.RuleGroup)
|
||||
for i := range statusRuleGroups {
|
||||
g := statusRuleGroups[i]
|
||||
// the matchers only filter rules and all groups still return,
|
||||
// and some of them may be with empty rules, so here check them and skip some.
|
||||
if len(g.Rules) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := statusRuleGroupMap[g.Name]; !ok {
|
||||
statusRuleGroupMap[g.Name] = g
|
||||
}
|
||||
}
|
||||
// copy status info of statusRuleGroups to matched rulegroups
|
||||
var groups = make([]runtime.Object, len(resourceRuleGroups.Items))
|
||||
for i := range resourceRuleGroups.Items {
|
||||
g := &kapialertingv2beta1.ClusterRuleGroup{
|
||||
ClusterRuleGroup: resourceRuleGroups.Items[i],
|
||||
Status: kapialertingv2beta1.RuleGroupStatus{
|
||||
State: promrules.StateInactive.String(),
|
||||
},
|
||||
}
|
||||
statusg, ok := statusRuleGroupMap[g.Name]
|
||||
if ok && len(statusg.Rules) == len(g.Spec.Rules) {
|
||||
copyRuleGroupStatus(statusg, &g.Status)
|
||||
}
|
||||
groups[i] = g
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) ListClusterRuleGroups(ctx context.Context,
|
||||
queryParam *query.Query) (*api.ListResult, error) {
|
||||
|
||||
groups, err := o.listClusterRuleGroups(ctx, queryParam.Selector())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resources.DefaultList(groups, queryParam, func(left, right runtime.Object, field query.Field) bool {
|
||||
hit, great := o.compareRuleGroupStatus(
|
||||
&(left.(*kapialertingv2beta1.ClusterRuleGroup).Status), &(right.(*kapialertingv2beta1.ClusterRuleGroup).Status), field)
|
||||
if hit {
|
||||
return great
|
||||
}
|
||||
return resources.DefaultObjectMetaCompare(
|
||||
left.(*kapialertingv2beta1.ClusterRuleGroup).ObjectMeta, right.(*kapialertingv2beta1.ClusterRuleGroup).ObjectMeta, field)
|
||||
}, func(obj runtime.Object, filter query.Filter) bool {
|
||||
hit, selected := o.filterRuleGroupStatus(&obj.(*kapialertingv2beta1.ClusterRuleGroup).Status, filter)
|
||||
if hit {
|
||||
return selected
|
||||
}
|
||||
return resources.DefaultObjectMetaFilter(obj.(*kapialertingv2beta1.ClusterRuleGroup).ObjectMeta, filter)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) ListClusterAlerts(ctx context.Context,
|
||||
queryParam *query.Query) (*api.ListResult, error) {
|
||||
|
||||
groups, err := o.listClusterRuleGroups(ctx, labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// encapsulated as runtime.Object for easy comparison and filtering.
|
||||
var alerts []runtime.Object
|
||||
for i := range groups {
|
||||
g := groups[i].(*kapialertingv2beta1.ClusterRuleGroup)
|
||||
for j := range g.Status.RulesStatus {
|
||||
ruleStatus := g.Status.RulesStatus[j]
|
||||
for k := range ruleStatus.Alerts {
|
||||
alerts = append(alerts, &wrapAlert{Alert: *ruleStatus.Alerts[k]})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filterAlert := o.createFilterAlertFunc(queryParam)
|
||||
listResult := resources.DefaultList(alerts, queryParam, func(left, right runtime.Object, field query.Field) bool {
|
||||
return o.compareAlert(&left.(*wrapAlert).Alert, &right.(*wrapAlert).Alert, field)
|
||||
}, func(obj runtime.Object, filter query.Filter) bool {
|
||||
return filterAlert(&obj.(*wrapAlert).Alert, filter)
|
||||
})
|
||||
for i := range listResult.Items {
|
||||
listResult.Items[i] = &listResult.Items[i].(*wrapAlert).Alert
|
||||
}
|
||||
return listResult, nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) GetClusterRuleGroup(ctx context.Context, name string) (*kapialertingv2beta1.ClusterRuleGroup, error) {
|
||||
resourceRuleGroup, err := o.ksclient.AlertingV2beta1().ClusterRuleGroups().Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &kapialertingv2beta1.ClusterRuleGroup{
|
||||
ClusterRuleGroup: *resourceRuleGroup,
|
||||
Status: kapialertingv2beta1.RuleGroupStatus{
|
||||
State: promrules.StateInactive.String(),
|
||||
},
|
||||
}
|
||||
|
||||
matchers := []*promlabels.Matcher{{
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyRuleLevel,
|
||||
Value: string(controller.RuleLevelCluster),
|
||||
}}
|
||||
statusRuleGroups, err := o.ruleClient.ThanosRules(ctx, matchers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, g := range statusRuleGroups {
|
||||
if g.Name == resourceRuleGroup.Name && len(g.Rules) == len(resourceRuleGroup.Spec.Rules) {
|
||||
copyRuleGroupStatus(g, &ret.Status)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) listGlobalRuleGroups(ctx context.Context, selector labels.Selector) ([]runtime.Object, error) {
|
||||
resourceRuleGroups, err := o.ksclient.AlertingV2beta1().GlobalRuleGroups().List(ctx,
|
||||
metav1.ListOptions{
|
||||
LabelSelector: selector.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get rules matching '{rule_level="global"}' from thanos ruler
|
||||
matchers := []*promlabels.Matcher{{
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyRuleLevel,
|
||||
Value: string(controller.RuleLevelGlobal),
|
||||
}}
|
||||
statusRuleGroups, err := o.ruleClient.ThanosRules(ctx, matchers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var statusRuleGroupMap = make(map[string]*alerting.RuleGroup)
|
||||
for i := range statusRuleGroups {
|
||||
g := statusRuleGroups[i]
|
||||
// the matchers only filter rules and all groups still return,
|
||||
// and some of them may be with empty rules, so here check them and skip some.
|
||||
if len(g.Rules) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := statusRuleGroupMap[g.Name]; !ok {
|
||||
statusRuleGroupMap[g.Name] = g
|
||||
}
|
||||
}
|
||||
// copy status info of statusRuleGroups to matched rulegroups
|
||||
var groups = make([]runtime.Object, len(resourceRuleGroups.Items))
|
||||
for i := range resourceRuleGroups.Items {
|
||||
g := &kapialertingv2beta1.GlobalRuleGroup{
|
||||
GlobalRuleGroup: resourceRuleGroups.Items[i],
|
||||
Status: kapialertingv2beta1.RuleGroupStatus{
|
||||
State: promrules.StateInactive.String(),
|
||||
},
|
||||
}
|
||||
statusg, ok := statusRuleGroupMap[g.Name]
|
||||
if ok && len(statusg.Rules) == len(g.Spec.Rules) {
|
||||
copyRuleGroupStatus(statusg, &g.Status)
|
||||
}
|
||||
groups[i] = g
|
||||
}
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) ListGlobalRuleGroups(ctx context.Context,
|
||||
queryParam *query.Query) (*api.ListResult, error) {
|
||||
|
||||
groups, err := o.listGlobalRuleGroups(ctx, queryParam.Selector())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resources.DefaultList(groups, queryParam, func(left, right runtime.Object, field query.Field) bool {
|
||||
hit, great := o.compareRuleGroupStatus(
|
||||
&(left.(*kapialertingv2beta1.GlobalRuleGroup).Status), &(right.(*kapialertingv2beta1.GlobalRuleGroup).Status), field)
|
||||
if hit {
|
||||
return great
|
||||
}
|
||||
return resources.DefaultObjectMetaCompare(
|
||||
left.(*kapialertingv2beta1.GlobalRuleGroup).ObjectMeta, right.(*kapialertingv2beta1.GlobalRuleGroup).ObjectMeta, field)
|
||||
}, func(obj runtime.Object, filter query.Filter) bool {
|
||||
hit, selected := o.filterRuleGroupStatus(&obj.(*kapialertingv2beta1.GlobalRuleGroup).Status, filter)
|
||||
if hit {
|
||||
return selected
|
||||
}
|
||||
return resources.DefaultObjectMetaFilter(obj.(*kapialertingv2beta1.GlobalRuleGroup).ObjectMeta, filter)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) ListGlobalAlerts(ctx context.Context,
|
||||
queryParam *query.Query) (*api.ListResult, error) {
|
||||
|
||||
groups, err := o.listGlobalRuleGroups(ctx, labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// encapsulated as runtime.Object for easy comparison and filtering.
|
||||
var alerts []runtime.Object
|
||||
for i := range groups {
|
||||
wrapg := groups[i].(*kapialertingv2beta1.GlobalRuleGroup)
|
||||
for j := range wrapg.Status.RulesStatus {
|
||||
ruleStatus := wrapg.Status.RulesStatus[j]
|
||||
for k := range ruleStatus.Alerts {
|
||||
alerts = append(alerts, &wrapAlert{Alert: *ruleStatus.Alerts[k]})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filterAlert := o.createFilterAlertFunc(queryParam)
|
||||
listResult := resources.DefaultList(alerts, queryParam, func(left, right runtime.Object, field query.Field) bool {
|
||||
return o.compareAlert(&left.(*wrapAlert).Alert, &right.(*wrapAlert).Alert, field)
|
||||
}, func(obj runtime.Object, filter query.Filter) bool {
|
||||
return filterAlert(&obj.(*wrapAlert).Alert, filter)
|
||||
})
|
||||
for i := range listResult.Items {
|
||||
listResult.Items[i] = &listResult.Items[i].(*wrapAlert).Alert
|
||||
}
|
||||
return listResult, nil
|
||||
}
|
||||
|
||||
func (o *ruleGroupOperator) GetGlobalRuleGroup(ctx context.Context, name string) (*kapialertingv2beta1.GlobalRuleGroup, error) {
|
||||
resourceRuleGroup, err := o.ksclient.AlertingV2beta1().GlobalRuleGroups().Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &kapialertingv2beta1.GlobalRuleGroup{
|
||||
GlobalRuleGroup: *resourceRuleGroup,
|
||||
Status: kapialertingv2beta1.RuleGroupStatus{
|
||||
State: promrules.StateInactive.String(),
|
||||
},
|
||||
}
|
||||
|
||||
matchers := []*promlabels.Matcher{{
|
||||
Type: promlabels.MatchEqual,
|
||||
Name: controller.RuleLabelKeyRuleLevel,
|
||||
Value: string(controller.RuleLevelGlobal),
|
||||
}}
|
||||
statusRuleGroups, err := o.ruleClient.ThanosRules(ctx, matchers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, g := range statusRuleGroups {
|
||||
if g.Name == resourceRuleGroup.Name && len(g.Rules) == len(resourceRuleGroup.Spec.Rules) {
|
||||
copyRuleGroupStatus(g, &ret.Status)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// copyRuleGroupStatus copies group/rule status and alerts from source to target
|
||||
func copyRuleGroupStatus(source *alerting.RuleGroup, target *kapialertingv2beta1.RuleGroupStatus) {
|
||||
target.LastEvaluation = source.LastEvaluation
|
||||
if source.EvaluationTime > 0 {
|
||||
target.EvaluationTime = &source.EvaluationTime
|
||||
}
|
||||
groupState := promrules.StateInactive
|
||||
for i := range source.Rules {
|
||||
rule := source.Rules[i]
|
||||
// the group state takes the max state of its rules
|
||||
if ruleState := parseAlertState(rule.State); ruleState > groupState {
|
||||
groupState = ruleState
|
||||
}
|
||||
alerts := []*kapialertingv2beta1.Alert{}
|
||||
for _, alert := range rule.Alerts {
|
||||
alerts = append(alerts, &kapialertingv2beta1.Alert{
|
||||
ActiveAt: alert.ActiveAt,
|
||||
Annotations: alert.Annotations,
|
||||
Labels: alert.Labels,
|
||||
State: alert.State,
|
||||
Value: alert.Value,
|
||||
})
|
||||
}
|
||||
target.RulesStatus = append(target.RulesStatus, kapialertingv2beta1.RuleStatus{
|
||||
State: rule.State,
|
||||
Health: rule.Health,
|
||||
LastError: rule.LastError,
|
||||
EvaluationTime: rule.EvaluationTime,
|
||||
LastEvaluation: rule.LastEvaluation,
|
||||
Alerts: alerts,
|
||||
})
|
||||
}
|
||||
target.State = groupState.String()
|
||||
}
|
||||
|
||||
var (
|
||||
statePendingString = promrules.StatePending.String()
|
||||
stateFiringString = promrules.StateFiring.String()
|
||||
stateInactiveString = promrules.StateInactive.String()
|
||||
)
|
||||
|
||||
// parseAlertState parses state string to the AlertState type
|
||||
func parseAlertState(state string) promrules.AlertState {
|
||||
switch state {
|
||||
case statePendingString:
|
||||
return promrules.StatePending
|
||||
case stateFiringString:
|
||||
return promrules.StateFiring
|
||||
case stateInactiveString:
|
||||
fallthrough
|
||||
default:
|
||||
return promrules.StateInactive
|
||||
}
|
||||
}
|
||||
|
||||
type wrapAlert struct {
|
||||
kapialertingv2beta1.Alert
|
||||
runtime.Object
|
||||
}
|
||||
@@ -298,7 +298,9 @@ func getAlertingRuleStatus(resRule *ResourceRuleItem, epRule *alerting.AlertingR
|
||||
}
|
||||
rule.LastError = epRule.LastError
|
||||
rule.LastEvaluation = epRule.LastEvaluation
|
||||
rule.EvaluationDurationSeconds = epRule.EvaluationTime
|
||||
if epRule.EvaluationTime != nil {
|
||||
rule.EvaluationDurationSeconds = *epRule.EvaluationTime
|
||||
}
|
||||
|
||||
rState := strings.ToLower(epRule.State)
|
||||
cliRuleStateEmpty := rState == ""
|
||||
@@ -349,11 +351,13 @@ func ParseAlertingRules(epRuleGroups []*alerting.RuleGroup, custom bool, level v
|
||||
Labels: r.Labels,
|
||||
Annotations: r.Annotations,
|
||||
},
|
||||
State: r.State,
|
||||
Health: string(r.Health),
|
||||
LastError: r.LastError,
|
||||
LastEvaluation: r.LastEvaluation,
|
||||
EvaluationDurationSeconds: r.EvaluationTime,
|
||||
State: r.State,
|
||||
Health: string(r.Health),
|
||||
LastError: r.LastError,
|
||||
LastEvaluation: r.LastEvaluation,
|
||||
}
|
||||
if r.EvaluationTime != nil {
|
||||
rule.EvaluationDurationSeconds = *r.EvaluationTime
|
||||
}
|
||||
if rule.Health != "" {
|
||||
rule.Health = string(rules.HealthUnknown)
|
||||
|
||||
Reference in New Issue
Block a user