enhance globalrulegroups (#5134)

Signed-off-by: junot <junotxiang@kubesphere.io>

Signed-off-by: junot <junotxiang@kubesphere.io>
This commit is contained in:
junot
2022-08-12 20:30:33 +08:00
committed by GitHub
parent f741bc7943
commit b97a49b925
8 changed files with 555 additions and 21 deletions

View File

@@ -20,6 +20,7 @@ import (
"fmt"
"strings"
"github.com/prometheus/prometheus/pkg/labels"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
@@ -33,6 +34,8 @@ type Comparator string
type Severity string
type MatchType string
const (
ComparatorLT Comparator = "<"
ComparatorLE Comparator = "<="
@@ -42,6 +45,11 @@ const (
SeverityWarning Severity = "warning"
SeverityError Severity = "error"
SeverityCritical Severity = "critical"
MatchEqual = "="
MatchNotEqual = "!="
MatchRegexp = "=~"
MatchNotRegexp = "!~"
)
type Rule struct {
@@ -71,7 +79,91 @@ type ClusterRule struct {
}
type GlobalRule struct {
Rule `json:",inline"`
ClusterSelector *MetricLabelSelector `json:"clusterSelector,omitempty"`
NamespaceSelector *MetricLabelSelector `json:"namespaceSelector,omitempty"`
Rule `json:",inline"`
// If ExprBuilder is not nil, the configured Expr will be ignored
ExprBuilder *GlobalRuleExprBuilder `json:"exprBuilder,omitempty"`
}
// Only one of its members may be specified.
type MetricLabelSelector struct {
InValues []string `json:"inValues,omitempty"`
Matcher *Matcher `json:"matcher,omitempty"`
}
func (s *MetricLabelSelector) ParseToMatcher(labelName string) *labels.Matcher {
if s == nil {
return nil
}
if len(s.InValues) == 1 {
return &labels.Matcher{
Type: labels.MatchEqual,
Name: labelName,
Value: s.InValues[0],
}
}
if len(s.InValues) > 1 {
return &labels.Matcher{
Type: labels.MatchRegexp,
Name: labelName,
Value: fmt.Sprintf("(%s)", strings.Join(s.InValues, "|")),
}
}
if s.Matcher != nil {
var mtype labels.MatchType
switch s.Matcher.Type {
case MatchEqual:
mtype = labels.MatchEqual
case MatchNotEqual:
mtype = labels.MatchNotEqual
case MatchRegexp:
mtype = labels.MatchRegexp
case MatchNotRegexp:
mtype = labels.MatchNotRegexp
default:
return nil
}
return &labels.Matcher{
Type: mtype,
Name: labelName,
Value: s.Matcher.Value,
}
}
return nil
}
func (s *MetricLabelSelector) Validate() error {
if s.Matcher != nil {
return s.Matcher.Validate()
}
return nil
}
type Matcher struct {
Type MatchType `json:"type"`
Value string `json:"value,omitempty"`
}
func (m *Matcher) Validate() error {
var mtype labels.MatchType
switch m.Type {
case MatchEqual:
mtype = labels.MatchEqual
case MatchNotEqual:
mtype = labels.MatchNotEqual
case MatchRegexp:
mtype = labels.MatchRegexp
case MatchNotRegexp:
mtype = labels.MatchNotRegexp
default:
return fmt.Errorf("unsupported match type [%s]", m.Type)
}
_, err := labels.NewMatcher(mtype, "name", m.Value)
if err != nil {
return fmt.Errorf("invalid matcher: %v", err)
}
return nil
}
type NamespaceRuleExprBuilder struct {
@@ -82,6 +174,12 @@ type ClusterRuleExprBuilder struct {
Node *NodeExprBuilder `json:"node,omitempty"`
}
// Only one of its members may be specified.
type GlobalRuleExprBuilder struct {
Workload *WorkloadExprBuilder `json:"workload,omitempty"`
Node *NodeExprBuilder `json:"node,omitempty"`
}
type WorkloadKind string
const (

View File

@@ -212,6 +212,20 @@ func (r *GlobalRuleGroup) SetupWebhookWithManager(mgr ctrl.Manager) error {
var _ webhook.Defaulter = &GlobalRuleGroup{}
func (r *GlobalRuleGroup) Default() {
log := globalrulegrouplog.WithValues("name", r.Name)
log.Info("default")
for i := range r.Spec.Rules {
rule := r.Spec.Rules[i]
if rule.ExprBuilder != nil {
if rule.ExprBuilder.Node != nil {
rule.Expr = intstr.FromString(rule.ExprBuilder.Node.Build())
} else if rule.ExprBuilder.Workload != nil {
rule.Expr = intstr.FromString(rule.ExprBuilder.Workload.Build())
}
}
r.Spec.Rules[i] = rule
}
}
var _ webhook.Validator = &GlobalRuleGroup{}
@@ -231,6 +245,16 @@ func (r *GlobalRuleGroup) Validate() error {
var rules []Rule
for _, r := range r.Spec.Rules {
if r.ClusterSelector != nil {
if err := r.ClusterSelector.Validate(); err != nil {
return err
}
}
if r.NamespaceSelector != nil {
if err := r.NamespaceSelector.Validate(); err != nil {
return err
}
}
rules = append(rules, r.Rule)
}
var err = validateRules(log, r.Name, r.Spec.Interval, rules)

View File

@@ -171,7 +171,22 @@ func (in *ClusterRuleGroupStatus) DeepCopy() *ClusterRuleGroupStatus {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlobalRule) DeepCopyInto(out *GlobalRule) {
*out = *in
if in.ClusterSelector != nil {
in, out := &in.ClusterSelector, &out.ClusterSelector
*out = new(MetricLabelSelector)
(*in).DeepCopyInto(*out)
}
if in.NamespaceSelector != nil {
in, out := &in.NamespaceSelector, &out.NamespaceSelector
*out = new(MetricLabelSelector)
(*in).DeepCopyInto(*out)
}
in.Rule.DeepCopyInto(&out.Rule)
if in.ExprBuilder != nil {
in, out := &in.ExprBuilder, &out.ExprBuilder
*out = new(GlobalRuleExprBuilder)
(*in).DeepCopyInto(*out)
}
return
}
@@ -185,6 +200,32 @@ func (in *GlobalRule) DeepCopy() *GlobalRule {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlobalRuleExprBuilder) DeepCopyInto(out *GlobalRuleExprBuilder) {
*out = *in
if in.Workload != nil {
in, out := &in.Workload, &out.Workload
*out = new(WorkloadExprBuilder)
(*in).DeepCopyInto(*out)
}
if in.Node != nil {
in, out := &in.Node, &out.Node
*out = new(NodeExprBuilder)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalRuleExprBuilder.
func (in *GlobalRuleExprBuilder) DeepCopy() *GlobalRuleExprBuilder {
if in == nil {
return nil
}
out := new(GlobalRuleExprBuilder)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlobalRuleGroup) DeepCopyInto(out *GlobalRuleGroup) {
*out = *in
@@ -285,6 +326,48 @@ func (in *GlobalRuleGroupStatus) DeepCopy() *GlobalRuleGroupStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Matcher) DeepCopyInto(out *Matcher) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Matcher.
func (in *Matcher) DeepCopy() *Matcher {
if in == nil {
return nil
}
out := new(Matcher)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MetricLabelSelector) DeepCopyInto(out *MetricLabelSelector) {
*out = *in
if in.InValues != nil {
in, out := &in.InValues, &out.InValues
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Matcher != nil {
in, out := &in.Matcher, &out.Matcher
*out = new(Matcher)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricLabelSelector.
func (in *MetricLabelSelector) DeepCopy() *MetricLabelSelector {
if in == nil {
return nil
}
out := new(MetricLabelSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NamespaceRule) DeepCopyInto(out *NamespaceRule) {
*out = *in