mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
feat: introduce evaluation results in cel engine (#11971)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
07a23746d8
commit
9d11e8f98c
2 changed files with 64 additions and 45 deletions
|
@ -2,9 +2,11 @@ package engine
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||
"github.com/kyverno/kyverno/pkg/cel/policy"
|
||||
"github.com/kyverno/kyverno/pkg/cel/utils"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/handlers"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
|
@ -72,14 +74,23 @@ func (e *engine) Handle(ctx context.Context, request EngineRequest) (EngineRespo
|
|||
|
||||
func (e *engine) handlePolicy(ctx context.Context, policy policy.CompiledPolicy, resource *unstructured.Unstructured, namespace *unstructured.Unstructured) PolicyResponse {
|
||||
var rules []engineapi.RuleResponse
|
||||
ok, err := policy.Evaluate(ctx, resource, namespace)
|
||||
// TODO: evaluation should be per rule
|
||||
results, err := policy.Evaluate(ctx, resource, namespace)
|
||||
// TODO: error is about match conditions here ?
|
||||
if err != nil {
|
||||
rules = handlers.WithResponses(engineapi.RuleError("todo", engineapi.Validation, "failed to load context", err, nil))
|
||||
} else if ok {
|
||||
rules = handlers.WithResponses(engineapi.RulePass("todo", engineapi.Validation, "success", nil))
|
||||
rules = handlers.WithResponses(engineapi.RuleError("evaluation", engineapi.Validation, "failed to load context", err, nil))
|
||||
} else {
|
||||
rules = handlers.WithResponses(engineapi.RuleFail("todo", engineapi.Validation, "failure", nil))
|
||||
for index, result := range results {
|
||||
ruleName := fmt.Sprintf("rule-%d", index)
|
||||
if result.Error != nil {
|
||||
rules = append(rules, *engineapi.RuleError(ruleName, engineapi.Validation, "error", err, nil))
|
||||
} else if result, err := utils.ConvertToNative[bool](result.Result); err != nil {
|
||||
rules = append(rules, *engineapi.RuleError(ruleName, engineapi.Validation, "conversion error", err, nil))
|
||||
} else if result {
|
||||
rules = append(rules, *engineapi.RulePass(ruleName, engineapi.Validation, "success", nil))
|
||||
} else {
|
||||
rules = append(rules, *engineapi.RuleFail(ruleName, engineapi.Validation, "failure", nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
return PolicyResponse{
|
||||
// TODO
|
||||
|
|
|
@ -18,8 +18,13 @@ type (
|
|||
namespace = *unstructured.Unstructured
|
||||
)
|
||||
|
||||
type EvaluationResult struct {
|
||||
Result ref.Val
|
||||
Error error
|
||||
}
|
||||
|
||||
type CompiledPolicy interface {
|
||||
Evaluate(context.Context, resource, namespace) (bool, error)
|
||||
Evaluate(context.Context, resource, namespace) ([]EvaluationResult, error)
|
||||
}
|
||||
|
||||
type compiledPolicy struct {
|
||||
|
@ -30,19 +35,18 @@ type compiledPolicy struct {
|
|||
auditAnnotations map[string]cel.Program
|
||||
}
|
||||
|
||||
func (p *compiledPolicy) Evaluate(ctx context.Context, resource resource, namespace namespace) (bool, error) {
|
||||
func (p *compiledPolicy) Evaluate(ctx context.Context, resource resource, namespace namespace) ([]EvaluationResult, error) {
|
||||
match, err := p.match(ctx, resource, namespace)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
if !match {
|
||||
return true, nil
|
||||
return nil, nil
|
||||
}
|
||||
var nsData map[string]any
|
||||
if namespace != nil {
|
||||
nsData = namespace.UnstructuredContent()
|
||||
}
|
||||
variables := func() map[string]any {
|
||||
vars := lazy.NewMapValue(VariablesType)
|
||||
data := map[string]any{
|
||||
NamespaceObjectKey: nsData,
|
||||
|
@ -61,26 +65,30 @@ func (p *compiledPolicy) Evaluate(ctx context.Context, resource resource, namesp
|
|||
return nil
|
||||
})
|
||||
}
|
||||
return data
|
||||
}
|
||||
data := variables()
|
||||
results := make([]EvaluationResult, 0, len(p.validations))
|
||||
for _, rule := range p.validations {
|
||||
out, _, err := rule.Eval(data)
|
||||
// check error
|
||||
if err != nil {
|
||||
return false, err
|
||||
results = append(results, EvaluationResult{
|
||||
Result: out,
|
||||
Error: err,
|
||||
})
|
||||
// // check error
|
||||
// if err != nil {
|
||||
// results = append(results, EvaluationResult{
|
||||
// Error: err,
|
||||
// })
|
||||
// }
|
||||
// response, err := utils.ConvertToNative[bool](out)
|
||||
// // check error
|
||||
// if err != nil {
|
||||
// return false, err
|
||||
// }
|
||||
// // if response is false, return
|
||||
// if !response {
|
||||
// return false, nil
|
||||
// }
|
||||
}
|
||||
response, err := utils.ConvertToNative[bool](out)
|
||||
// check error
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// if response is false, return
|
||||
if !response {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (p *compiledPolicy) match(ctx context.Context, resource resource, namespace namespace) (bool, error) {
|
||||
|
|
Loading…
Add table
Reference in a new issue