1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

refactor: simplify engine responses (#6804)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-04-06 00:55:42 +02:00 committed by GitHub
parent 04d410d321
commit de00c78513
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 49 additions and 51 deletions

View file

@ -92,15 +92,18 @@ func Test_buildPolicyReports(t *testing.T) {
er := engineapi.EngineResponse{} er := engineapi.EngineResponse{}
er.Policy = &policy er.Policy = &policy
er.PolicyResponse.Add(engineapi.ExecutionStats{}, *engineapi.RuleFail( er.PolicyResponse.Add(
"pods-require-account", engineapi.ExecutionStats{},
engineapi.Validation, *engineapi.RuleFail(
"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/"), "pods-require-account",
) engineapi.Validation,
er.PolicyResponse.Add(engineapi.ExecutionStats{}, *engineapi.RulePass( "validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/",
"pods-require-limits", ),
engineapi.Validation, *engineapi.RulePass(
"validation rule 'pods-require-limits' passed."), "pods-require-limits",
engineapi.Validation,
"validation rule 'pods-require-limits' passed.",
),
) )
info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false) info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false)
@ -137,15 +140,17 @@ func Test_buildPolicyResults(t *testing.T) {
er := engineapi.EngineResponse{} er := engineapi.EngineResponse{}
er.Policy = &policy er.Policy = &policy
er.PolicyResponse.Add(engineapi.ExecutionStats{}, *engineapi.RuleFail( er.PolicyResponse.Add(
"pods-require-account", engineapi.ExecutionStats{}, *engineapi.RuleFail(
engineapi.Validation, "pods-require-account",
"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/"), engineapi.Validation,
) "validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/",
er.PolicyResponse.Add(engineapi.ExecutionStats{}, *engineapi.RulePass( ),
"pods-require-limits", *engineapi.RulePass(
engineapi.Validation, "pods-require-limits",
"validation rule 'pods-require-limits' passed."), engineapi.Validation,
"validation rule 'pods-require-limits' passed.",
),
) )
info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false) info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false)

View file

@ -33,9 +33,9 @@ func generateSuccessEvents(log logr.Logger, ers ...engineapi.EngineResponse) (ev
func generateExceptionEvents(log logr.Logger, ers ...engineapi.EngineResponse) (eventInfos []event.Info) { func generateExceptionEvents(log logr.Logger, ers ...engineapi.EngineResponse) (eventInfos []event.Info) {
for _, er := range ers { for _, er := range ers {
for i, ruleResp := range er.PolicyResponse.Rules { for _, ruleResp := range er.PolicyResponse.Rules {
if ruleResp.Status() == engineapi.RuleStatusSkip && ruleResp.IsException() { if ruleResp.Status() == engineapi.RuleStatusSkip && ruleResp.IsException() {
eventInfos = append(eventInfos, event.NewPolicyExceptionEvents(er, &er.PolicyResponse.Rules[i], event.PolicyController)...) eventInfos = append(eventInfos, event.NewPolicyExceptionEvents(er, ruleResp, event.PolicyController)...)
} }
} }
} }
@ -57,11 +57,11 @@ func generateFailEventsPerEr(log logr.Logger, er engineapi.EngineResponse) []eve
"namespace", er.Resource.GetNamespace(), "namespace", er.Resource.GetNamespace(),
"name", er.Resource.GetName(), "name", er.Resource.GetName(),
) )
for i, rule := range er.PolicyResponse.Rules { for _, rule := range er.PolicyResponse.Rules {
if rule.Status() != engineapi.RuleStatusPass && rule.Status() != engineapi.RuleStatusSkip { if rule.Status() != engineapi.RuleStatusPass && rule.Status() != engineapi.RuleStatusSkip {
eventResource := event.NewResourceViolationEvent(event.PolicyController, event.PolicyViolation, er, &er.PolicyResponse.Rules[i]) eventResource := event.NewResourceViolationEvent(event.PolicyController, event.PolicyViolation, er, rule)
eventInfos = append(eventInfos, eventResource) eventInfos = append(eventInfos, eventResource)
eventPolicy := event.NewPolicyFailEvent(event.PolicyController, event.PolicyViolation, er, &er.PolicyResponse.Rules[i], false) eventPolicy := event.NewPolicyFailEvent(event.PolicyController, event.PolicyViolation, er, rule, false)
eventInfos = append(eventInfos, eventPolicy) eventInfos = append(eventInfos, eventPolicy)
} }
} }

View file

@ -8,13 +8,15 @@ type PolicyResponse struct {
Rules []RuleResponse Rules []RuleResponse
} }
func (pr *PolicyResponse) Add(stats ExecutionStats, response RuleResponse) { func (pr *PolicyResponse) Add(stats ExecutionStats, responses ...RuleResponse) {
pr.Rules = append(pr.Rules, response.WithStats(stats)) for _, response := range responses {
status := response.Status() pr.Rules = append(pr.Rules, response.WithStats(stats))
if status == RuleStatusPass || status == RuleStatusFail { status := response.Status()
pr.Stats.RulesAppliedCount++ if status == RuleStatusPass || status == RuleStatusFail {
} else if status == RuleStatusError { pr.Stats.RulesAppliedCount++
pr.Stats.RulesErrorCount++ } else if status == RuleStatusError {
pr.Stats.RulesErrorCount++
}
} }
} }

View file

@ -53,10 +53,7 @@ func (e *engine) verifyAndPatchImages(
engineapi.ImageVerify, engineapi.ImageVerify,
) )
matchedResource = resource matchedResource = resource
stats := engineapi.NewExecutionStats(startTime, time.Now()) resp.Add(engineapi.NewExecutionStats(startTime, time.Now()), ruleResp...)
for _, ruleResp := range ruleResp {
resp.Add(stats, ruleResp)
}
if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 { if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 {
break break
} }

View file

@ -50,10 +50,7 @@ func (e *engine) mutate(
engineapi.Mutation, engineapi.Mutation,
) )
matchedResource = resource matchedResource = resource
stats := engineapi.NewExecutionStats(startTime, time.Now()) resp.Add(engineapi.NewExecutionStats(startTime, time.Now()), ruleResp...)
for _, ruleResp := range ruleResp {
resp.Add(stats, ruleResp)
}
if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 { if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 {
break break
} }

View file

@ -68,10 +68,7 @@ func (e *engine) validate(
engineapi.Validation, engineapi.Validation,
) )
matchedResource = resource matchedResource = resource
stats := engineapi.NewExecutionStats(startTime, time.Now()) resp.Add(engineapi.NewExecutionStats(startTime, time.Now()), ruleResp...)
for _, ruleResp := range ruleResp {
resp.Add(stats, ruleResp)
}
if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 { if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 {
break break
} }

View file

@ -9,7 +9,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
) )
func NewPolicyFailEvent(source Source, reason Reason, engineResponse engineapi.EngineResponse, ruleResp *engineapi.RuleResponse, blocked bool) Info { func NewPolicyFailEvent(source Source, reason Reason, engineResponse engineapi.EngineResponse, ruleResp engineapi.RuleResponse, blocked bool) Info {
return Info{ return Info{
Kind: getPolicyKind(engineResponse.Policy), Kind: getPolicyKind(engineResponse.Policy),
Name: engineResponse.Policy.GetName(), Name: engineResponse.Policy.GetName(),
@ -20,7 +20,7 @@ func NewPolicyFailEvent(source Source, reason Reason, engineResponse engineapi.E
} }
} }
func buildPolicyEventMessage(resp *engineapi.RuleResponse, resource engineapi.ResourceSpec, blocked bool) string { func buildPolicyEventMessage(resp engineapi.RuleResponse, resource engineapi.ResourceSpec, blocked bool) string {
var b strings.Builder var b strings.Builder
if resource.Namespace != "" { if resource.Namespace != "" {
fmt.Fprintf(&b, "%s %s/%s", resource.Kind, resource.Namespace, resource.Name) fmt.Fprintf(&b, "%s %s/%s", resource.Kind, resource.Namespace, resource.Name)
@ -68,7 +68,7 @@ func NewPolicyAppliedEvent(source Source, engineResponse engineapi.EngineRespons
} }
} }
func NewResourceViolationEvent(source Source, reason Reason, engineResponse engineapi.EngineResponse, ruleResp *engineapi.RuleResponse) Info { func NewResourceViolationEvent(source Source, reason Reason, engineResponse engineapi.EngineResponse, ruleResp engineapi.RuleResponse) Info {
var bldr strings.Builder var bldr strings.Builder
defer bldr.Reset() defer bldr.Reset()
@ -123,7 +123,7 @@ func NewBackgroundSuccessEvent(policy, rule string, source Source, r *unstructur
return events return events
} }
func NewPolicyExceptionEvents(engineResponse engineapi.EngineResponse, ruleResp *engineapi.RuleResponse, source Source) []Info { func NewPolicyExceptionEvents(engineResponse engineapi.EngineResponse, ruleResp engineapi.RuleResponse, source Source) []Info {
exception := ruleResp.Exception() exception := ruleResp.Exception()
exceptionName, exceptionNamespace := exception.GetName(), exception.GetNamespace() exceptionName, exceptionNamespace := exception.GetName(), exception.GetNamespace()
policyMessage := fmt.Sprintf("resource %s was skipped from rule %s due to policy exception %s/%s", resourceKey(engineResponse.PatchedResource), ruleResp.Name(), exceptionNamespace, exceptionName) policyMessage := fmt.Sprintf("resource %s was skipped from rule %s due to policy exception %s/%s", resourceKey(engineResponse.PatchedResource), ruleResp.Name(), exceptionNamespace, exceptionName)

View file

@ -20,20 +20,20 @@ func GenerateEvents(engineResponses []engineapi.EngineResponse, blocked bool) []
continue continue
} }
if !er.IsSuccessful() { if !er.IsSuccessful() {
for i, ruleResp := range er.PolicyResponse.Rules { for _, ruleResp := range er.PolicyResponse.Rules {
if ruleResp.Status() == engineapi.RuleStatusFail || ruleResp.Status() == engineapi.RuleStatusError { if ruleResp.Status() == engineapi.RuleStatusFail || ruleResp.Status() == engineapi.RuleStatusError {
e := event.NewPolicyFailEvent(event.AdmissionController, event.PolicyViolation, er, &er.PolicyResponse.Rules[i], blocked) e := event.NewPolicyFailEvent(event.AdmissionController, event.PolicyViolation, er, ruleResp, blocked)
events = append(events, e) events = append(events, e)
} }
if !blocked { if !blocked {
e := event.NewResourceViolationEvent(event.AdmissionController, event.PolicyViolation, er, &er.PolicyResponse.Rules[i]) e := event.NewResourceViolationEvent(event.AdmissionController, event.PolicyViolation, er, ruleResp)
events = append(events, e) events = append(events, e)
} }
} }
} else if er.IsSkipped() { // Handle PolicyException Event } else if er.IsSkipped() { // Handle PolicyException Event
for i, ruleResp := range er.PolicyResponse.Rules { for _, ruleResp := range er.PolicyResponse.Rules {
if ruleResp.Status() == engineapi.RuleStatusSkip && !blocked && ruleResp.IsException() { if ruleResp.Status() == engineapi.RuleStatusSkip && !blocked && ruleResp.IsException() {
events = append(events, event.NewPolicyExceptionEvents(er, &er.PolicyResponse.Rules[i], event.AdmissionController)...) events = append(events, event.NewPolicyExceptionEvents(er, ruleResp, event.AdmissionController)...)
} }
} }
} else if !er.IsSkipped() { } else if !er.IsSkipped() {