1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 15:37:19 +00:00
kyverno/pkg/engine/variables/variables.go
Shivkumar Dudhani ffd2179b03
538 (#587)
* initial commit

* background policy validation

* correct message

* skip non-background policy process for add/update

* add Generate Request CR

* generate Request Generator Initial

* test generate request CR generation

* initial commit gr generator

* generate controller initial framework

* add crd for generate request

* gr cleanup controller initial commit

* cleanup controller initial

* generate mid-commit

* generate rule processing

* create PV on generate error

* embed resource type

* testing phase 1- generate resources with variable substitution

* fix tests

* comment broken test #586

* add printer column for state

* return if existing resource for clone

* set resync time to 2 mins & remove resource version check in update handler for gr

* generate events for reporting

* fix logs

* cleanup

* CR fixes

* fix logs
2020-01-07 10:33:28 -08:00

102 lines
3 KiB
Go

package variables
import (
"regexp"
"strings"
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/engine/context"
"github.com/nirmata/kyverno/pkg/engine/operator"
)
//SubstituteVariables substitutes the JMESPATH with variable substitution
// supported substitutions
// - no operator + variable(string,object)
// unsupported substitutions
// - operator + variable(object) -> as we dont support operators with object types
func SubstituteVariables(ctx context.EvalInterface, pattern interface{}) interface{} {
// var err error
switch typedPattern := pattern.(type) {
case map[string]interface{}:
return substituteMap(ctx, typedPattern)
case []interface{}:
return substituteArray(ctx, typedPattern)
case string:
// variable substitution
return substituteValue(ctx, typedPattern)
default:
return pattern
}
}
func substituteMap(ctx context.EvalInterface, patternMap map[string]interface{}) map[string]interface{} {
for key, patternElement := range patternMap {
value := SubstituteVariables(ctx, patternElement)
patternMap[key] = value
}
return patternMap
}
func substituteArray(ctx context.EvalInterface, patternList []interface{}) []interface{} {
for idx, patternElement := range patternList {
value := SubstituteVariables(ctx, patternElement)
patternList[idx] = value
}
return patternList
}
func substituteValue(ctx context.EvalInterface, valuePattern string) interface{} {
// patterns supported
// - operator + string
// operator + variable
operatorVariable := getOperator(valuePattern)
variable := valuePattern[len(operatorVariable):]
// substitute variable with value
value := getValueQuery(ctx, variable)
if operatorVariable == "" {
// default or operator.Equal
// equal + string variable
// object variable
return value
}
// operator + string variable
switch value.(type) {
case string:
return string(operatorVariable) + value.(string)
default:
glog.Infof("cannot use operator with object variables. operator used %s in pattern %v", string(operatorVariable), valuePattern)
var emptyInterface interface{}
return emptyInterface
}
}
func getValueQuery(ctx context.EvalInterface, valuePattern string) interface{} {
var emptyInterface interface{}
// extract variable {{<variable>}}
variableRegex := regexp.MustCompile("{{(.*)}}")
groups := variableRegex.FindStringSubmatch(valuePattern)
if len(groups) < 2 {
return valuePattern
}
searchPath := groups[1]
// search for the path in ctx
variable, err := ctx.Query(searchPath)
if err != nil {
glog.V(4).Infof("variable substitution failed for query %s: %v", searchPath, err)
return emptyInterface
}
// only replace the value if returned value is scalar
if val, ok := variable.(string); ok {
newVal := strings.Replace(valuePattern, groups[0], val, -1)
return newVal
}
return variable
}
func getOperator(pattern string) string {
operatorVariable := operator.GetOperatorFromStringPattern(pattern)
if operatorVariable == operator.Equal {
return ""
}
return string(operatorVariable)
}