1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-01-20 18:52:16 +00:00
kyverno/pkg/engine/context/mock_context.go
Jim Bugwadia 46f02a8ba7
optimize JSON context processing using in-memory maps (#8322)
* optimize JSON context processing using in memory maps

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix excessive logs

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix mutate resource diff

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* uncomment tests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* copy resource, as it can be modified

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* clear prior resource to prevent mutating original

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* linter fix

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix ImageInfo to unstructured conversion

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix custom image extractors

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* do not update mutated resource in JSON context

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* address review comments

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

---------

Signed-off-by: Jim Bugwadia <jim@nirmata.com>
Signed-off-by: shuting <shuting@nirmata.com>
Co-authored-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>
Co-authored-by: shuting <shuting@nirmata.com>
2023-12-04 07:35:36 +00:00

112 lines
2.8 KiB
Go

package context
import (
"fmt"
"regexp"
"strings"
"sync"
"github.com/kyverno/kyverno/ext/wildcard"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
)
// MockContext is used for testing and validation of variables
type MockContext struct {
mutex sync.RWMutex
re *regexp.Regexp
allowedPatterns []string
}
// NewMockContext creates a new MockContext that allows variables matching the supplied list of wildcard patterns
func NewMockContext(re *regexp.Regexp, vars ...string) *MockContext {
return &MockContext{re: re, allowedPatterns: vars}
}
// AddVariable adds given wildcardPattern to the allowed variable patterns
func (ctx *MockContext) AddVariable(wildcardPattern string) {
ctx.mutex.Lock()
defer ctx.mutex.Unlock()
builtInVarsCopy := ctx.allowedPatterns
ctx.allowedPatterns = append(builtInVarsCopy, wildcardPattern)
}
// Query the JSON context with JMESPATH search path
func (ctx *MockContext) Query(query string) (interface{}, error) {
query = strings.TrimSpace(query)
if query == "" {
return nil, fmt.Errorf("invalid query (nil)")
}
var emptyResult interface{}
// compile the query
jp := jmespath.New(config.NewDefaultConfiguration(false))
if _, err := jp.Query(query); err != nil {
return emptyResult, fmt.Errorf("invalid JMESPath query %s: %v", query, err)
}
// strip escaped quotes from JMESPath variables with dashes e.g. {{ \"my-map.data\".key }}
query = strings.Replace(query, "\"", "", -1)
if ctx.re != nil && ctx.re.MatchString(query) {
return emptyResult, nil
}
if ctx.isVariableDefined(query) {
return emptyResult, nil
}
return emptyResult, InvalidVariableError{
variable: query,
re: ctx.re,
allowedPatterns: ctx.allowedPatterns,
}
}
func (ctx *MockContext) QueryOperation() string {
if op, err := ctx.Query("request.operation"); err != nil {
if op != nil {
return op.(string)
}
}
return ""
}
func (ctx *MockContext) isVariableDefined(variable string) bool {
for _, pattern := range ctx.getVariables() {
if wildcard.Match(pattern, variable) {
return true
}
}
return false
}
func (ctx *MockContext) getVariables() []string {
ctx.mutex.RLock()
defer ctx.mutex.RUnlock()
vars := ctx.allowedPatterns
return vars
}
// InvalidVariableError represents error for non-white-listed variables
type InvalidVariableError struct {
variable string
re *regexp.Regexp
allowedPatterns []string
}
func (i InvalidVariableError) Error() string {
if i.re == nil {
return fmt.Sprintf("variable %s must match patterns %v", i.variable, i.allowedPatterns)
}
return fmt.Sprintf("variable %s must match regex \"%s\" or patterns %v", i.variable, i.re.String(), i.allowedPatterns)
}
func (ctx *MockContext) HasChanged(_ string) (bool, error) {
return false, nil
}