2019-12-30 17:08:50 -08:00
|
|
|
package context
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2020-01-09 12:23:05 -08:00
|
|
|
"fmt"
|
2020-05-06 00:29:40 +05:30
|
|
|
"strings"
|
2019-12-30 17:08:50 -08:00
|
|
|
|
2023-03-24 11:01:49 +01:00
|
|
|
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
2019-12-30 17:08:50 -08:00
|
|
|
)
|
|
|
|
|
2022-04-09 13:52:50 +02:00
|
|
|
// Query the JSON context with JMESPATH search path
|
|
|
|
func (ctx *context) Query(query string) (interface{}, error) {
|
2023-05-05 17:35:47 -07:00
|
|
|
if err := ctx.loadDeferred(query); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-11-24 17:53:19 -08:00
|
|
|
query = strings.TrimSpace(query)
|
|
|
|
if query == "" {
|
|
|
|
return nil, fmt.Errorf("invalid query (nil)")
|
|
|
|
}
|
2019-12-30 17:08:50 -08:00
|
|
|
// compile the query
|
2023-04-13 13:29:40 +02:00
|
|
|
queryPath, err := ctx.jp.Query(query)
|
2019-12-30 17:08:50 -08:00
|
|
|
if err != nil {
|
2022-04-09 13:52:50 +02:00
|
|
|
logger.Error(err, "incorrect query", "query", query)
|
|
|
|
return nil, fmt.Errorf("incorrect query %s: %v", query, err)
|
2019-12-30 17:08:50 -08:00
|
|
|
}
|
|
|
|
// search
|
2021-02-01 23:22:19 -08:00
|
|
|
ctx.mutex.RLock()
|
|
|
|
defer ctx.mutex.RUnlock()
|
2019-12-30 17:08:50 -08:00
|
|
|
var data interface{}
|
|
|
|
if err := json.Unmarshal(ctx.jsonRaw, &data); err != nil {
|
2023-02-01 14:38:04 +08:00
|
|
|
return nil, fmt.Errorf("failed to unmarshal context: %w", err)
|
2019-12-30 17:08:50 -08:00
|
|
|
}
|
|
|
|
result, err := queryPath.Search(data)
|
|
|
|
if err != nil {
|
2023-02-01 14:38:04 +08:00
|
|
|
return nil, fmt.Errorf("JMESPath query failed: %w", err)
|
2019-12-30 17:08:50 -08:00
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|
2020-02-14 11:59:28 -08:00
|
|
|
|
2023-05-05 17:35:47 -07:00
|
|
|
func (ctx *context) loadDeferred(query string) error {
|
2023-06-27 09:58:50 -07:00
|
|
|
level := len(ctx.jsonRawCheckpoints)
|
|
|
|
return ctx.deferred.LoadMatching(query, level)
|
2023-06-16 09:29:49 +02:00
|
|
|
}
|
|
|
|
|
2022-04-09 13:52:50 +02:00
|
|
|
func (ctx *context) HasChanged(jmespath string) (bool, error) {
|
2021-07-20 09:36:12 -07:00
|
|
|
objData, err := ctx.Query("request.object." + jmespath)
|
|
|
|
if err != nil {
|
2023-02-01 14:38:04 +08:00
|
|
|
return false, fmt.Errorf("failed to query request.object: %w", err)
|
2021-07-20 09:36:12 -07:00
|
|
|
}
|
|
|
|
if objData == nil {
|
|
|
|
return false, fmt.Errorf("request.object.%s not found", jmespath)
|
|
|
|
}
|
|
|
|
oldObjData, err := ctx.Query("request.oldObject." + jmespath)
|
|
|
|
if err != nil {
|
2023-02-01 14:38:04 +08:00
|
|
|
return false, fmt.Errorf("failed to query request.object: %w", err)
|
2021-07-20 09:36:12 -07:00
|
|
|
}
|
|
|
|
if oldObjData == nil {
|
|
|
|
return false, fmt.Errorf("request.oldObject.%s not found", jmespath)
|
|
|
|
}
|
2023-03-24 11:01:49 +01:00
|
|
|
return !datautils.DeepEqual(objData, oldObjData), nil
|
2021-07-20 09:36:12 -07:00
|
|
|
}
|