-
Notifications
You must be signed in to change notification settings - Fork 375
/
eval.go
74 lines (65 loc) · 2.33 KB
/
eval.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright (c) 2021 Terminus, Inc.
//
// This program is free software: you can use, redistribute, and/or modify
// it under the terms of the GNU Affero General Public License, version 3
// or later ("AGPL"), as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package pexpr
import (
"fmt"
"strings"
"gopkg.in/Knetic/govaluate.v3"
"github.com/erda-project/erda/pkg/strutil"
)
// Eval 递归渲染统一表达式语法里的占位符,再计算表达式结果
// exprStr: 表达式
// placeholderParams: 占位符参数
func Eval(exprStr string, placeholderParams map[string]string) (interface{}, error) {
// 校验表达式
invalidPhs := FindInvalidPlaceholders(exprStr)
if len(invalidPhs) > 0 {
return nil, fmt.Errorf("invalid expression, found invalid placeholders: %s (must match: %s)", strings.Join(invalidPhs, ", "), PhRe.String())
}
// 递归渲染表达式中的占位符
// 直到渲染完毕或找到不存在的占位符
for {
var notFoundPlaceholders []string
exprStr = strutil.ReplaceAllStringSubmatchFunc(PhRe, exprStr, func(subs []string) string {
ph := subs[0] // ${{ configs.key }}
inner := subs[1] // configs.key
v, ok := placeholderParams[inner]
if ok {
return v
}
notFoundPlaceholders = append(notFoundPlaceholders, ph)
return exprStr
})
if len(notFoundPlaceholders) > 0 {
return nil, fmt.Errorf("invalid expression, not found placeholders: %s", strings.Join(notFoundPlaceholders, ", "))
}
// 没有需要替换的占位符,则退出渲染
if !PhRe.MatchString(exprStr) {
break
}
}
// 计算表达式
expr, err := govaluate.NewEvaluableExpression(exprStr)
if err != nil {
return nil, fmt.Errorf("invalid expression: %s, err: %v", exprStr, err)
}
strParams := make(map[string]interface{}, len(placeholderParams))
for k, v := range placeholderParams {
strParams[k] = v
}
result, err := expr.Evaluate(strParams)
if err != nil {
return nil, fmt.Errorf("failed to evaluate expr, expr: %s, err: %v", exprStr, err)
}
return result, nil
}