You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.1 KiB
80 lines
2.1 KiB
package model |
|
|
|
import ( |
|
"encoding/json" |
|
"errors" |
|
"fmt" |
|
"go-common/app/service/live/zeus/expr" |
|
"go-common/library/log" |
|
) |
|
|
|
type Matcher struct { |
|
Group map[string][]*MatcherBucket `json:"group"` |
|
VariableWhitelist []string `json:"variable_whitelist"` |
|
} |
|
|
|
type MatcherBucket struct { |
|
RuleExpr string `json:"expr"` |
|
Extend interface{} `json:"extend"` |
|
expr expr.Expr |
|
variable []string |
|
config string |
|
} |
|
|
|
func NewMatcher(config string) (*Matcher, error) { |
|
matcher := &Matcher{} |
|
if err := json.Unmarshal([]byte(config), matcher); err != nil { |
|
return nil, err |
|
} |
|
whitelist := make(map[string]struct{}, len(matcher.VariableWhitelist)) |
|
for _, v := range matcher.VariableWhitelist { |
|
whitelist[v] = struct{}{} |
|
} |
|
parser := expr.NewExpressionParser() |
|
for _, bucket := range matcher.Group { |
|
for _, b := range bucket { |
|
if e := parser.Parse(b.RuleExpr); e != nil { |
|
msg := fmt.Sprintf("zeus compile error, rule:%s error:%s", b.RuleExpr, e.Error()) |
|
return nil, errors.New(msg) |
|
} |
|
b.expr = parser.GetExpr() |
|
b.variable = parser.GetVariable() |
|
for _, v := range b.variable { |
|
if _, ok := whitelist[v]; !ok { |
|
msg := fmt.Sprintf("zeus check error, rule:%s error: variable %s not in whitelist", b.RuleExpr, v) |
|
return nil, errors.New(msg) |
|
} |
|
} |
|
if config, e := json.Marshal(b.Extend); e != nil { |
|
msg := fmt.Sprintf("zeus parse config error, rule:%s error:%s", b.RuleExpr, e.Error()) |
|
return nil, errors.New(msg) |
|
} else { |
|
b.config = string(config) |
|
} |
|
} |
|
} |
|
return matcher, nil |
|
} |
|
|
|
func (m *Matcher) Match(group string, env expr.Env) (bool, string, error) { |
|
var bucket []*MatcherBucket |
|
var ok bool |
|
if bucket, ok = m.Group[group]; !ok { |
|
return false, "", errors.New("group not found") |
|
} |
|
isMatch := false |
|
extend := "" |
|
for _, b := range bucket { |
|
result, err := expr.EvalBool(b.expr, env) |
|
if err != nil { |
|
log.Error("zeus eval error, group:%s expr:%s error:%s", group, b.RuleExpr, err.Error()) |
|
continue |
|
} |
|
if result { |
|
isMatch = true |
|
extend = b.config |
|
break |
|
} |
|
} |
|
return isMatch, extend, nil |
|
}
|
|
|