1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/engine/variables/vars.go

124 lines
3.3 KiB
Go
Raw Normal View History

package variables
import (
"fmt"
"regexp"
"strconv"
"strings"
2020-03-17 11:05:20 -07:00
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/engine/context"
)
2020-11-25 00:21:51 -08:00
var regexVariables = regexp.MustCompile(`\{\{[^{}]*\}\}`)
//IsVariable returns true if the element contains a 'valid' variable {{}}
func IsVariable(element string) bool {
groups := regexVariables.FindAllStringSubmatch(element, -1)
return len(groups) != 0
}
2020-02-14 11:59:28 -08:00
//SubstituteVars replaces the variables with the values defined in the context
2020-11-24 17:48:54 -08:00
// - if any variable is invalid or has nil value, it is considered as a failed variable substitution
2020-03-17 11:05:20 -07:00
func SubstituteVars(log logr.Logger, ctx context.EvalInterface, pattern interface{}) (interface{}, error) {
2020-05-06 22:27:06 +05:30
pattern, err := subVars(log, ctx, pattern, "")
if err != nil {
return pattern, err
}
2020-05-06 22:27:06 +05:30
return pattern, nil
}
2020-05-06 22:27:06 +05:30
func subVars(log logr.Logger, ctx context.EvalInterface, pattern interface{}, path string) (interface{}, error) {
switch typedPattern := pattern.(type) {
case map[string]interface{}:
2020-04-09 22:00:24 +05:30
mapCopy := make(map[string]interface{})
for k, v := range typedPattern {
mapCopy[k] = v
}
2020-05-06 22:27:06 +05:30
return subMap(log, ctx, mapCopy, path)
2020-11-25 00:21:51 -08:00
case []interface{}:
2020-04-09 22:00:24 +05:30
sliceCopy := make([]interface{}, len(typedPattern))
copy(sliceCopy, typedPattern)
2020-05-06 22:27:06 +05:30
return subArray(log, ctx, sliceCopy, path)
2020-11-25 00:21:51 -08:00
case string:
2020-11-25 00:21:51 -08:00
return subValR(log, ctx, typedPattern, path)
default:
2020-05-06 22:27:06 +05:30
return pattern, nil
}
}
2020-05-06 22:27:06 +05:30
func subMap(log logr.Logger, ctx context.EvalInterface, patternMap map[string]interface{}, path string) (map[string]interface{}, error) {
for key, patternElement := range patternMap {
curPath := path + "/" + key
2020-05-06 22:27:06 +05:30
value, err := subVars(log, ctx, patternElement, curPath)
if err != nil {
return nil, err
}
patternMap[key] = value
}
2020-05-06 22:27:06 +05:30
return patternMap, nil
}
2020-05-06 22:27:06 +05:30
func subArray(log logr.Logger, ctx context.EvalInterface, patternList []interface{}, path string) ([]interface{}, error) {
for idx, patternElement := range patternList {
curPath := path + "/" + strconv.Itoa(idx)
2020-05-06 22:27:06 +05:30
value, err := subVars(log, ctx, patternElement, curPath)
if err != nil {
return nil, err
}
patternList[idx] = value
}
2020-05-06 22:27:06 +05:30
return patternList, nil
}
2020-11-17 13:07:30 -08:00
// NotFoundVariableErr ...
2020-05-13 10:06:21 +05:30
type NotFoundVariableErr struct {
variable string
path string
}
func (n NotFoundVariableErr) Error() string {
return fmt.Sprintf("variable %v not found (path: %v)", n.variable, n.path)
2020-05-13 10:06:21 +05:30
}
2020-02-26 16:41:48 -08:00
// subValR resolves the variables if defined
2020-11-25 00:21:51 -08:00
func subValR(log logr.Logger, ctx context.EvalInterface, valuePattern string, path string) (interface{}, error) {
2020-05-05 23:52:52 +05:30
originalPattern := valuePattern
2020-11-25 00:21:51 -08:00
vars := regexVariables.FindAllString(valuePattern, -1)
for _, v := range vars {
variable := strings.ReplaceAll(v, "{{", "")
variable = strings.ReplaceAll(variable, "}}", "")
variable = strings.TrimSpace(variable)
substitutedVar, err := ctx.Query(variable)
if err != nil {
return nil, fmt.Errorf("failed to resolve %v at path %s", variable, path)
}
log.V(3).Info("variable substituted", "variable", v, "value", substitutedVar, "path", path)
if val, ok := substitutedVar.(string); ok {
valuePattern = strings.Replace(valuePattern, v, val, -1)
continue
}
2020-02-26 16:41:48 -08:00
2020-11-25 00:21:51 -08:00
if substitutedVar != nil {
if originalPattern == variable {
return substitutedVar, nil
2020-02-26 16:41:48 -08:00
}
2020-11-25 00:21:51 -08:00
return nil, fmt.Errorf("failed to resolve %v at path %s", variable, path)
}
return nil, NotFoundVariableErr{
variable: variable,
path: path,
2020-02-26 16:41:48 -08:00
}
}
2020-05-06 22:27:06 +05:30
return valuePattern, nil
}